NodeJS,如何避免在AWS Lambda @ Edge中发送只读标头?

时间:2019-07-18 09:46:59

标签: node.js amazon-s3 aws-lambda

我已经在Cloudfront上设置了Lambda以使用图像上的width和height参数动态调整图像的大小,因此我在下面添加了代码

(我没有写这段代码,我不记得从哪里得到的代码)

const querystring = require('querystring');
const http = require('http');
const https = require('https');
const fs = require('fs');
const child = require('child_process');

// headers that cloudfront does not allow in the http response
const blacklistedHeaders = [
    /^connection$/i,
    /^content-length$/i,
    /^expect$/i,
    /^keep-alive$/i,
    /^proxy-authenticate$/i,
    /^proxy-authorization$/i,
    /^proxy-connection$/i,
    /^trailer$/i,
    /^upgrade$/i,
    /^x-accel-buffering$/i,
    /^x-accel-charset$/i,
    /^x-accel-limit-rate$/i,
    /^x-accel-redirect$/i,
    /^X-Amz-Cf-.*/i,
    /^X-Amzn-.*/i,
    /^X-Cache.*/i,
    /^X-Edge-.*/i,
    /^X-Forwarded-Proto.*/i,
    /^X-Real-IP$/i
];

exports.handler = (event, context, callback) => {
    console.log(JSON.stringify(event, null, 2));
    const request = event.Records[0].cf.request;
    const origin = request.origin.custom;
    const protocol = origin.protocol;
    const tmpPath = '/tmp/sourceImage';
    const targetPath = '/tmp/targetImage';

    const getFile = origin.protocol === 'https' ?
        https.get :
        http.get;

    const options = querystring.parse(request.querystring);
    const maxSize = 5000;
    const width = Math.min(options.width || maxSize, maxSize);
    const height = Math.min(options.height || maxSize, maxSize);

    // make sure input values are numbers
    if (Number.isNaN(width) || Number.isNaN(height)) {
        console.log('Invalid input');
        context.succeed({
            status: '400',
            statusDescription: 'Invalid input'
        });
        return;
    }

    // dowload the file from the origin server
    getFile(`${origin.protocol}://${origin.domainName}${origin.path}${request.uri}`, (res) => {
        const statusCode = res.statusCode;
        console.log(res.headers);

        // grab headers from the origin request and reformat them
        // to match the lambda@edge return format
        const originHeaders = Object.keys(res.headers)
        // some headers we get back from the origin
        // must be filtered out because they are blacklisted by cloudfront
        .filter((header) => blacklistedHeaders.every((blheader) => !blheader.test(header)))
        .reduce((acc, header) => {
            acc[header.toLowerCase()] = [
                {
                    key: header,
                    value: res.headers[header]
                }
            ];
            return acc;
        }, {})

        if (statusCode === 200) {
            const writeStream = fs.createWriteStream(tmpPath);
            res
              .on('error', (e) => {
                  context.succeed({
                      status: '500',
                      statusDescription: 'Error downloading the image'
                  });
              })
              .pipe(writeStream)

            writeStream
            .on('finish', () => {
                console.log('image downloaded');

                try {
                    // invoke ImageMagick to resize the image
                    const stdout = child.execSync(
                        `convert ${tmpPath} -resize ${width}x${height}\\> -quality 80 ${targetPath}`
                    );
                } catch(e) {
                    console.log('ImageMagick error');
                    console.log(e.stderr.toString());
                    context.succeed({
                      status: '500',
                      statusDescription: 'Error resizing image'
                    });
                    return;
                }

                const image = fs.readFileSync(targetPath).toString('base64');

                context.succeed({
                    bodyEncoding: 'base64',
                    body: image,
                    headers: originHeaders,
                    status: '200',
                    statusDescription: 'OK'
                });
            })
            .on('error', (e) => {
                console.log(e);
                context.succeed({
                  status: '500',
                  statusDescription: 'Error writing the image to a file'
                });
            })
        } else {
            // grap the status code from the origin request
            // and return to the viewer
            console.log('statusCode: ', statusCode);
            context.succeed({
                status: statusCode.toString(),
                headers: originHeaders
            });
        }
    })
};

我在一些图像上而不是全部图像上出现502错误

Lambda函数结果验证失败:该函数尝试添加,删除或更改只读标头。

0 个答案:

没有答案