首页 文章

通过AWS API网关和Lambda函数返回动态内容类型

提问于
浏览
1

我想使用AWS API Gateway作为代理,从S3存储桶中获取文件并将其返回给客户端 . 我正在使用Lambda函数与S3交谈,并通过AWS API Gateway将文件发送到客户端 . 我已经知道,最好的方法是使用“Lambda代理集成”,这样整个请求就可以通过管道传输给Lambda而无需任何修改 . 但是,如果我这样做,那么我无法为我的Lambda函数的结果响应设置集成响应 . 所以客户端获得的是JSON .

似乎应该有一种方法让API网关获取JSON并将请求转换为客户端的正确响应,但我似乎无法弄清楚如何实现这一点 . 有很多示例指向手动设置API网关响应的内容类型,但我需要将内容类型标头设置为文件类型 .

对于图像和二进制格式,我的Lambda函数返回base64编码的字符串,属性 isBase64Encoded 设置为 true . 当我转到"Binary Support"部分并指定像 image/* 这样的内容类型应该作为二进制返回时,它不起作用 . 我只是通过将二进制支持内容类型设置为 */* (也称为所有内容)来获得成功,这对于非二进制内容类型不起作用 .

我错过了什么,为什么这看起来如此困难?

1 回答

  • 1

    原来API网关不是问题 . 我的Lambda函数没有返回正确的 Headers .

    为了处理二进制响应,我发现你需要将二进制支持内容类型设置为 */* (也就是所有内容),然后让你的Lambda函数返回属性 isBase64Encoded 设置为 true . base64编码并以此方式指示的响应将被解码并作为二进制提供,而其他请求将按原样返回 .

    这是Lambda函数的简单Gist,它接受给定路径并从S3读取文件并通过API网关返回:

    /**
     * This is a simple AWS Lambda function that will look for a given file on S3 and return it
     * passing along all of the headers of the S3 file. To make this available via a URL use
     * API Gateway with an AWS Lambda Proxy Integration.
     * 
     * Set the S3_REGION and S3_BUCKET global parameters in AWS Lambda
     * Make sure the Lambda function is passed an object with `{ pathParameters : { proxy: 'path/to/file.jpg' } }` set
     */
    
    var AWS = require('aws-sdk');
    
    exports.handler = function( event, context, callback ) {
        var region = process.env.S3_REGION;
        var bucket = process.env.S3_BUCKET;
        var key = decodeURI( event.pathParameters.proxy );
    
        // Basic server response
        /*
        var response = {
            statusCode: 200,
            headers: {
                'Content-Type': 'text/plain',
            },
            body: "Hello world!",
        };
        callback( null, response );
        */
    
        // Fetch from S3
        var s3 = new AWS.S3( Object.assign({ region: region }) );
        return s3.makeUnauthenticatedRequest(
            'getObject',
            { Bucket: bucket, Key: key },
            function(err, data) {
                if (err) {
                    return err;
                }
    
                var isBase64Encoded = false;
                if ( data.ContentType.indexOf('image/') > -1 ) {
                    isBase64Encoded = true;
                }
    
                var encoding = '';
                if ( isBase64Encoded ) {
                    encoding = 'base64'
                }
                var resp = {
                    statusCode: 200,
                    headers: {
                        'Content-Type': data.ContentType,
                    },
                    body: new Buffer(data.Body).toString(encoding),
                    isBase64Encoded: isBase64Encoded
                };
    
                callback(null, resp);
            }
        );
    };
    

    通过https://gist.github.com/kingkool68/26aa7a3641a3851dc70ce7f44f589350

相关问题