I recently (finally) finished moving all articles from my old wiki — to this blog. Once that was done I needed to forward all URLs to their new location.
My site is hosted with AWS CloudFront, so I made a simple redirect function and deployed it to AWS Lambda@Edge.
Table of contents
New function
In the AWS console; navigate to the Lambda service. Make sure the location is N. Virginia, this is required for Lambda@Edge.
Make a new function:
- Click Create function, top right
- Author from scratch
- Enter a function name
- Choose Node.js 12.x (latest one supported by Lambda@Edge)
- Click Create function
The function consists of three files:
index.js
, the actual function scriptredir.json
, list of redirectsregex.json
, list of regex redirects
My index.js
looks like this;
const redirectsRegex = require('./regex.json').map(
({ source, destination }) => ({
source: new RegExp(source, 'i'),
destination
})
);
const redirectsStatic = require('./redir.json').map(
({ source, destination }) => ({
source,
destination
})
);
exports.handler = async (event) => {
const request = event.Records[0].cf.request;
for (const { source, destination } of redirectsRegex) {
if (source.test(request.uri)) {
return {
status: '301',
statusDescription: 'Moved Permanently',
headers: {
location: [{ value: destination }]
}
};
}
}
for (const { source, destination } of redirectsStatic) {
if (source == request.uri) {
return {
status: '301',
statusDescription: 'Moved Permanently',
headers: {
location: [{ value: destination }]
}
};
}
}
return {
status: '302',
statusDescription: 'Found',
headers: {
location: [{ value: 'https://blog.cavelab.dev' + request.uri }]
}
};
};
It’s pretty basic; it loads regex.json
and redir.json
as constants. Then it searches through them, if a match it found it returns a 301 Moved Permanently
to the destination URL.
If no matches are found, it returns a 302 Found
to https://blog.cavelab.dev + request.uri
.
Here are is an entry from redir.json
:
[
{
"source": "/projects/tagged/bascom",
"destination": "https://blog.cavelab.dev/tags/bascom/"
}
]
And from regex.json
:
[
{
"source": "/(wiki|w)/Main_Page$",
"destination": "https://blog.cavelab.dev/"
},
{
"source": "^/(wiki|w)/?$",
"destination": "https://blog.cavelab.dev/"
}
]
Sources in the redir.json
must be a direct match with the request.uri
, while sources in regex.json
must match the regular expression.
Permissions
To have permission to deploy the function to the edge, we first need to add some trust relationships:
- Navigate to Identity and Access Management (IAM)
- Go to Roles
- Click the role for the function you just created, it will be named something like function_name-role-xxxxxxxx
- Go to the Trust relationships tab
- Click Edit trust relationship
- Add
edgelambda.amazonaws.com
to the Service array, making it look like this:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"edgelambda.amazonaws.com",
"lambda.amazonaws.com"
]
},
"Action": "sts:AssumeRole"
}
]
}
Deploy
Alright — time to deploy! Navigate back to the Lambda function we created earlier.
On the function page;
- Click Add trigger
- Choose CloudFront
- Click Deploy to Lambda@Edge
- Leave it on Configure new CloudFront trigger
- Choose your distribution and cache behaviour
- Set CloudFront event to Origin request
- Check Confirm deploy to Lambda@Edge
Deployed!
If you now navigate to the CloudFront distribution and behaviour you selected, you should see it under Edge Function Associations.
Redeploy
If you make any changes to the function, it needs to be redeployed to the edge.
You can do that on the function page:
- Click the Actions button, top right
- Click Deploy to Lambda@Edge
- Select Use existing CloudFront trigger on this function
- Click Deploy
Domains
The redirect function doesn’t care about the domain, only the path. So whatever domain you use as alternative names for the CloudFront distribution will get redirected.
Remember to add both the naked domain and the www
subdomain.
Last commit 2024-11-11, with message: Add lots of tags to posts.