Как передать файл с S3 через Meteor Iron Router

Мой вопрос очень похож на этот, который описывает, как обслуживать локальный файл с помощью Iron Router. Мне нужно сделать то же самое, но вместо синхронного чтения файла с диска мне нужно получить файл из S3, который является асинхронным вызовом.

Проблема, по-видимому, заключается в том, что метод action вернулся до завершения асинхронного s3.getObject, что привело к следующей ошибке.

Error: Can't render headers after they are sent to the client.

Я предполагаю, что Iron Router генерирует для меня ответ, когда он понимает, что я не обработал ответ в моем action методе, но я не понимаю, как сказать ему дождаться завершения моего асинхронного вызова.

Вот мой код.

Router.map(function () {
    this.route('resumeDownload', {
        where: 'server',
        path: '/resume/:_id',
        action: function () {
            var response = this.response;

            var candidate = Candidates.findOne(this.params._id);
            if (!candidate || !candidate.resumeS3Key) {
                // this works fine because the method hasn't returned yet.
                response.writeHead(404);
                return response.end();
            }

            var s3 = new AWS.S3();
            s3.getObject({Bucket: 'myBucket', Key: candidate.resumeS3Key}, function (err, data) {
                if (err) {
                    // this will cause the error to be displayed
                    response.writeHead(500);
                    return response.end();
                }
                // this will also cause the error to be displayed
                response.writeHead(200, {'Content-Type': data.ContentType});
                response.end(data.Body);
            });
        }
    });
});

person Craig M    schedule 19.03.2014    source источник


Ответы (1)


Я сам смог решить эту проблему. Мне нужно было использовать future в моем action методе.

Вот рабочий код.

Router.map(function () {
    this.route('resumeDownload', {
        where: 'server',
        path: '/resume/:_id',
        action: function () {
            var response = this.response,
                candidate = Candidates.findOne(this.params._id);

            if (!candidate || !candidate.resumeS3Key) {
                response.writeHead(404);
                return response.end();
            }

            var Future = Npm.require('fibers/future'),
                s3 = new AWS.S3(),
                futureGetObject = Future.wrap(s3.getObject.bind(s3)),
                data = futureGetObject({Bucket: 'myBucket', Key: candidate.resumeS3Key}).wait();

            response.writeHead(200, {'Content-Type': data.ContentType});
            response.end(data.Body);
        }
    });
});
person Craig M    schedule 19.03.2014