Skip to content

Instantly share code, notes, and snippets.

@javanigus
Created October 30, 2023 05:45
Show Gist options
  • Save javanigus/46d9bad88a9244d2789dc00c41912a8f to your computer and use it in GitHub Desktop.
Save javanigus/46d9bad88a9244d2789dc00c41912a8f to your computer and use it in GitHub Desktop.
AWS Lambda Function to Redirect HTTP Requests by Reading JSON Data in S3
const REDIRECTS_DATA_REGION = 'us-east-1';
const REDIRECTS_DATA_BUCKET = 'pdfs';
const REDIRECTS_DATA_OBJECT = 'docs/pdf-redirects.json';
// https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/s3/command/GetObjectCommand/
import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3";
const client = new S3Client({
region: REDIRECTS_DATA_REGION
});
async function readFile(bucketName, filename) {
const input = { Bucket: bucketName, Key: filename };
const command = new GetObjectCommand(input);
const response = await client.send(command);
return response.Body.transformToString();
}
async function getRedirectsData() {
const txt = await readFile(REDIRECTS_DATA_BUCKET, REDIRECTS_DATA_OBJECT);
let data;
try {
data = JSON.parse(txt);
} catch (e) {
console.error('getRedirectsData parse failed', txt, e);
data = {};
}
return data;
}
const supportedStatusCodes = {
301: 'Moved Permanently',
302: 'Found',
307: 'Temporary Redirect',
};
export const handler = async (event, context) => {
// Get the incoming request and the initial response from S3
// https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-event-structure.html
const { request, response } = event.Records[0].cf;
// request.uri is just the URL path without hostname or querystring
let path = request.uri;
// Cut off trailing slash to normalize it
if (path.slice(-1) === '/') {
path = path.slice(0, -1);
}
const redirectsData = await getRedirectsData();
const redirectData = redirectsData[path];
// See if a redirect exists & sanity check that the redirect object is what we expect
const shouldRedirect = !!(
redirectData &&
redirectData.to &&
supportedStatusCodes[redirectData.statusCode]
);
if (shouldRedirect) {
// Note: We can't completely create a new set of headers even for a redirect
// because Cloudfront fails painfully if you set (or clear) a "read-only" header.
// For Origin Response triggers, that includes leaving "Transfer-Encoding" alone.
// https://github.com/awsdocs/amazon-cloudfront-developer-guide/blob/master/doc_source/lambda-requirements-limits.md#read-only-headers
response.headers['location'] = [
{
key: 'Location',
value: redirectData.to,
},
];
return {
status: redirectData.statusCode,
statusDescription: supportedStatusCodes[redirectData.statusCode],
headers: response.headers,
};
}
return response;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment