Last active
July 3, 2023 06:31
-
-
Save Kavan72/bbb99b9eb504b696353c9f70a8666b79 to your computer and use it in GitHub Desktop.
Static Next.js serve on s3 with CloudFront
This file contains hidden or 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' | |
const TTL = 10000 | |
const S3_REGION = '' // Update this with your s3 region | |
const S3_BUCKET_NAME = '' // Update this with your s3 bucket name | |
const S3_FILE_PATH = 'routes-manifest.json' | |
const s3 = new S3Client({ region: S3_REGION }) | |
const s3Params = { | |
Bucket: S3_BUCKET_NAME, | |
Key: S3_FILE_PATH | |
} | |
let jsonFile | |
const pullStream = async body => { | |
const buffers = [] | |
for await (const chunk of body) { | |
buffers.push(Buffer.from(chunk)) | |
} | |
return Buffer.concat(buffers) | |
} | |
const getRoutes = async () => { | |
if (jsonFile) return jsonFile | |
const response = await s3.send(new GetObjectCommand(s3Params)) | |
jsonFile = JSON.parse(await pullStream(response.Body)) | |
setTimeout(() => (jsonFile = undefined), TTL) | |
return jsonFile | |
} | |
const getOriginPath = async clientPath => { | |
const { staticRoutes, dynamicRoutes } = await getRoutes() | |
const staticUserRoute = staticRoutes.find(obj => clientPath.match(obj['regex'])) | |
const dynamicUserRoute = dynamicRoutes.find(obj => clientPath.match(obj['regex'])) | |
let redirectPage | |
let routeParams | |
if (staticUserRoute) { | |
redirectPage = staticUserRoute['page'] | |
} else if (dynamicUserRoute) { | |
routeParams = {} | |
const regex = new RegExp(dynamicUserRoute.namedRegex) | |
const matches = regex.exec(clientPath) | |
for (const key in dynamicUserRoute.routeKeys) { | |
const newKey = key.replace('nxtP', '') | |
routeParams[newKey] = matches.groups[key] | |
} | |
redirectPage = dynamicUserRoute.page | |
for (const param in routeParams) { | |
redirectPage = redirectPage.replace(`[${param}]`, routeParams[param]) | |
} | |
} else { | |
return '/404.html' | |
} | |
return redirectPage.endsWith('/') ? `${redirectPage}index.html` : `${redirectPage}/index.html` | |
} | |
export const handler = async (event, context, callback) => { | |
context.callbackWaitsForEmptyEventLoop = false | |
const request = event.Records[0].cf.request | |
const { uri } = request | |
console.log(`URI: ${uri}`) | |
if (uri.indexOf('.') >= 0 || uri === '/') { | |
request.uri = uri === '/' ? '/index.html' : uri | |
return callback(null, request) | |
} | |
try { | |
request.uri = await getOriginPath(uri) | |
console.log(request.uri) | |
callback(null, request) | |
} 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