Created
January 18, 2023 07:33
-
-
Save mauritsl/18b1333b3891236f53644c1909b3b735 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { S3Client, GetObjectCommand } from '@aws-sdk/client-s3'; | |
import { resolve } from 'path'; | |
const s3 = new S3Client({ region: 'S3_REGION' }); | |
const s3Params = { | |
Bucket: 'S3_BUCKET_NAME', | |
Key: 'router-paths.txt' | |
}; | |
const TTL = 10000; | |
const pullStream = (body) => { | |
return new Promise((resolve, reject) => { | |
const buffers = []; | |
body.on('data', buf => { | |
buffers.push(Buffer.from(buf)); | |
}); | |
body.on('end', () => { | |
resolve(Buffer.concat(buffers)); | |
}); | |
body.on('error', reject); | |
}); | |
}; | |
let paths; | |
const getPaths = async () => { | |
if (paths) { | |
return paths; | |
} | |
const response = await s3.send(new GetObjectCommand(s3Params)); | |
paths = (await pullStream(response.Body)).toString(); | |
setTimeout(() => { | |
paths = undefined; | |
}, TTL); | |
return paths; | |
}; | |
const getOriginPath = async clientPath => { | |
const clientParts = clientPath.substring(1).split('/'); | |
const paths = (await getPaths()) | |
.split('\n') | |
.map(s => s.trim()) | |
.filter(s => s); | |
for (let i = 0; i < paths.length; ++i) { | |
const parts = paths[i].split('.html')[0].split('/'); | |
const match = | |
parts.length === clientParts.length && | |
parts.reduce( | |
(match, part, index) => | |
match && | |
clientParts[index].length && | |
(part === clientParts[index] || part.startsWith('@') || part.startsWith('[')), | |
true | |
); | |
if (match) { | |
return '/' + paths[i]; | |
} | |
} | |
return '/404.html'; | |
}; | |
export const handler = (event, context, callback) => { | |
context.callbackWaitsForEmptyEventLoop = false; | |
const request = event.Records[0].cf.request; | |
const headers = request.headers; | |
const origin = request.origin; | |
// Ignore static files. | |
if (request.uri.indexOf('.') >= 0) { | |
callback(null, request); | |
return; | |
} | |
// Return 404 page for the paths config file. | |
if (request.uri === '/router-paths.txt') { | |
request.uri = '/404.html'; | |
callback(null, request); | |
return; | |
} | |
// Homepage. | |
if (request.uri === '/') { | |
request.uri = '/index.html'; | |
callback(null, request); | |
return; | |
} | |
// Remove trailing slashes by redirect. | |
if (request.uri.endsWith('/')) { | |
const response = { | |
status: '302', | |
statusDescription: 'Found', | |
headers: { | |
location: [ | |
{ | |
key: 'Location', | |
value: request.uri.substring(0, request.uri.length - 1) | |
} | |
] | |
} | |
}; | |
callback(null, response); | |
return; | |
} | |
// Lookup path in paths text file. | |
getOriginPath(request.uri) | |
.then(path => { | |
request.uri = path; | |
callback(null, request); | |
return; | |
}) | |
.catch(err => { | |
console.log(err); | |
callback(null, request); | |
}); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment