移动服务 + DocumentDB 附件

Mobile Service + DocumentDB attachment

这是我的堆栈:

我想要做的是从我们的应用程序中提取 DocumentDB 的知识,因为我们正在构建白标签解决方案,我们可能需要 on-the-fly 扩展 DocumentDB 实例。使用抽象类型的服务,我们基本上可以根据从应用程序发送的某些数据来分片我们的 docdb 实例。

现在这将包含 2 个操作,我想为其创建移动服务。一个用于获取 JSON 数据,另一个用于获取与文档关联的附件。这就是我的麻烦所在。我有一个仅用 NodeJS 编写的可部署的 pass-through 服务。我喜欢与移动服务相关的安全模型,所以我想调整我的代码以适应它。问题在于通过管道将 DocDB 响应传递给移动服务响应。首先是移动服务默认值 headers 试图设置但失败了,所以我暂时覆盖了该功能。现在移动服务从不响应,直到发生超时。这是一个代码片段:

exports.get = function (req, res) {
...
// .then().fail() always pushed into the fail() block, but if I use the 2 function in .then() way it works.
client.readMediaAsync(mediaUrl).then(
    // Success
    function (media) {
        // Set up caching and proxy the response
        media.headers["cache-control"] = "max-age=2147483647, max-stale=2147483647";
        media.headers["pragma"] = "cache";
        for (var responseHeader in media.headers) {
            if (media.headers.hasOwnProperty(responseHeader) && "content-location" != responseHeader) {
                res.setHeader(responseHeader, media.headers[responseHeader]);
            }
        }
        // Block further header modification
        res.setHeader = function(field, val){};
        media.result.pipe(res, {end: true});
        //media.result.on("end", function () {
        //    console.log("attachment#end");
        //    res.status(200).send(); // have also tried .end() with no luck
        //});
    },

    // Error
    function (mediaError) {
        console.error("documentClient.readMediaAsync fail->" + JSON.stringify(mediaError));
        res.status(400).send(JSON.stringify(mediaError));
    }
); ...

显示为 media.result.pipe(...) 的那一行是它被挂断的地方。同样,此代码在移动服务之外工作。我一直在使用 change -> commit -> test -> repeat cycle 但没有任何运气。有人知道如何正确地将流通过管道传输到移动服务中的响应吗?

我成功重现了你的问题,我请求了一段时间后得到了 HTML 代码,但是我在 LOGS 选项卡中也收到了错误消息,它看起来像:

An unhandled exception occurred. Error: Can't set headers after they are sent. at ServerResponse.OutgoingMessage.setHeader (http.js:679:11) at ServerResponse.res.setHeader (D:\home\site\wwwroot\node_modules\express\node_modules\connect\lib\patch.js:59:22) at ServerResponse.res.set.res.header (D:\home\site\wwwroot\node_modules\express\lib\response.js:518:10) at addDefaultHeaders (D:\home\site\wwwroot\runtime\request\requesthandler.js:582:9) at ServerResponse.<anonymous> (D:\home\site\wwwroot\runtime\request\requesthandler.js:291:13) at ServerResponse._.wrap [as end] (D:\home\site\wwwroot\node_modules\underscore\underscore.js:692:22) at onend (stream.js:66:10) at EventEmitter.emit (events.js:126:20) at afterRead (fs.js:1335:12) at Object.wrapper [as oncomplete] (fs.js:367:17)

根据这个日志,我在管道进入响应之前设置了 header,这在我的测试中运行良好。

这是我的简单代码片段: exports.get = function(request, response) { var fs = require("fs"); response.setHeader = function(field, val){}; fs.createReadStream('files/123.txt').pipe(response,{end: true}); };

我通过使用节点 documentdb sdk 的非承诺版本解决了这个问题。在响应中一定有什么东西与承诺混淆了(尽管它看起来很简单)。

这是功能代码片段: clientSync.readMedia(mediaUrl, function (err, mediaStream) { if (!err && mediaStream) { mediaStream.headers["cache-control"] = "max-age=2147483647, max-stale=2147483647"; mediaStream.headers["pragma"] = "cache"; for (var responseHeader in mediaStream.headers) { if (mediaStream.headers.hasOwnProperty(responseHeader) && "content-location" != responseHeader) { res.setHeader(responseHeader, mediaStream.headers[responseHeader]); } } res.setHeader = function (field, val) { }; mediaStream.pipe(res); mediaStream.on('end', function () { res.status(200).end(); }); } else { console.error("attachment(" + mediaUrl + ") catch->" + JSON.stringify(err.detail) + "; " + err.message + "; " + err.stack); res.status(400).send(); } });