diff --git a/package.json b/package.json index cfa5fc2..555334a 100644 --- a/package.json +++ b/package.json @@ -12,19 +12,21 @@ }, "devDependencies": { "@types/aws-lambda": "0.0.23", + "@types/etag": "1.8.0", "@types/node": "8.5.2", "ava": "0.23.0", "husky": "0.14.3", "lint-staged": "6.0.0", "prettier": "1.9.2", - "serverless-plugin-typescript": "1.1.5", - "serverless-apigwy-binary": "0.1.0" + "serverless-apigwy-binary": "0.1.0", + "serverless-plugin-typescript": "1.1.5" }, "dependencies": { "aws-sdk": "2.176.0", "graphql-request": "1.4.1", "lambda-helpers": "0.2.2", "sharp": "0.18.4", - "source-map-support": "0.5.0" + "source-map-support": "0.5.0", + "etag": "1.8.1" } } diff --git a/src/handler.ts b/src/handler.ts index 02d7a65..c8af038 100644 --- a/src/handler.ts +++ b/src/handler.ts @@ -3,6 +3,7 @@ import { getConfig, parseParams, Params } from './parser' import { callbackRuntime } from 'lambda-helpers' import { APIGatewayEvent, ProxyResult } from 'aws-lambda' import { GraphQLClient } from 'graphql-request' +const etag = require('etag') const sharp = require('sharp') import 'source-map-support/register' @@ -38,6 +39,7 @@ export default callbackRuntime(async (event: APIGatewayEvent) => { } } + const headerETag = event.headers['If-None-Match'] const [paramsErr, params] = parseParams(event.path) if (paramsErr) { @@ -57,7 +59,7 @@ export default callbackRuntime(async (event: APIGatewayEvent) => { const { ContentLength, ContentType, - ContentDisposition, + ContentDisposition } = await s3.headObject(options).promise() if (ContentLength! > 25 * 1024 * 1024) { @@ -82,7 +84,7 @@ export default callbackRuntime(async (event: APIGatewayEvent) => { ) { const obj = await s3.getObject(options).promise() const body = (obj.Body as Buffer).toString('base64') - return base64Response(body, ContentType!, ContentDisposition!) + return base64Response(body, ContentType!, ContentDisposition!, headerETag!) } const s3Resp = await s3.getObject(options).promise() @@ -125,6 +127,7 @@ export default callbackRuntime(async (event: APIGatewayEvent) => { buf.toString('base64'), ContentType!, ContentDisposition!, + headerETag! ) }) @@ -132,14 +135,26 @@ function base64Response( body: string, ContentType: string, ContentDisposition: string, + headerETag: string ) { + const bodyETag = etag(body); + const headers = { + 'Content-Type': ContentType, + 'Content-Disposition': ContentDisposition, + 'Cache-Control': 'max-age=31536000', + 'ETag': bodyETag + }; + + if(headerETag && headerETag === bodyETag){ + return { + statusCode: 304, + headers: headers + } + } + return { statusCode: 200, - headers: { - 'Content-Type': ContentType, - 'Content-Disposition': ContentDisposition, - 'Cache-Control': 'max-age=31536000', - }, + headers: headers, body, isBase64Encoded: true, }