Michael Harley
Michael Harley

Reputation: 1048

AWS CloudFront Rewrite to External URL

Background

I have a big repository that uses CRA React, and I need an SEO Feature in SSR. So I created a new NextJS 13 Repo and put only the page that needed the SEO Feature such as the Landing page in the NextJS. I want to implement an incremental adoption using the rewrite url so the user won't even notice the migration process.

What do I want to achieve?

I want to do a simple external URL rewrite: https://my-domain.com/company -> https://my-domain-legacy.com/company

Repositories and Infrastructure

So I'm creating an empty NextJS 13 with only index routing and deploying the NextJS with SST. I'm aware that NextJS provides a rewrites feature, but the external URL rewrite is not supported in SST currently, only the internal URL rewrites is supported.

Question

Do you have any suggestions as to what I can do to achieve what I want? Maybe an alternative to the SST library? Or how I can achieve this in LambdaEdge/CloudFront function?

What I have done so far?

I tried creating a simple internal URL rewrite in the LambdaEdge function:

exports.handler = (event, context, callback) => {
    const request = event.Records[0].cf.request;

    request.uri = request.uri
        .replace(/\/company$/,'/');

    return callback(null, request);
};

But I always get AccessDenied as a result when trying to access a page that isn't in the NextJS routing.

Edit 1:

Hi Dennis, this is my current function:

exports.handler = (event, context, callback) => {
    console.log(event);
    
    const request = event.Records[0].cf.request;

    // request.uri = request.uri
    //     .replace(/\/company$/,'/');
    request.origin.custom.domainName = "https://my-domain-legacy.com"
    

    return callback(null, request);
};

enter image description here

I tried to use the above code for my lambda function, but I get this error.

Current Lambda@Edge permission: enter image description here

Upvotes: 2

Views: 1713

Answers (2)

Michael Harley
Michael Harley

Reputation: 1048

I have successfully done a rewrite to an external URL (different domain).

This is my lambda@edge function:

const domainName = "my-domain-legacy.com";

exports.handler = (event, context, callback) => {
    const request = event.Records[0].cf.request;
    const newRequest = rewriteRequest(request);
    return callback(null, newRequest);
};

function rewriteRequest(request) {
    const newRequest = JSON.parse(JSON.stringify(request));
    newRequest.headers["host"] = [
        {
            "key": "Host",
            "value": domainName
        }
    ];
    newRequest.origin = {
        "custom": {
            "customHeaders": {},
            "domainName": domainName,
            "keepaliveTimeout": 5,
            "path": "",
            "port": 443,
            "protocol": "https",
            "readTimeout": 30,
            "sslProtocols": [
                "TLSv1",
                "TLSv1.1",
                "TLSv1.2"
            ]   
        }
    };
    return newRequest;
}

reference: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-examples.html#lambda-examples-content-based-custom-origin-request-trigger

Upvotes: 1

Dennis Traub
Dennis Traub

Reputation: 51634

Double-check the following line in your Lambda@Edge function:

request.uri = request.uri.replace(/\/company$/,'/');

Your current function replaces the path, not the domain. https://my-domain.com/company becomes https://my-domain.com/, while, according to your question, you want it to be https://my-domain-legacy.com/company.

Having that said, you can implement a proper redirect, including the HTTP code. There's an example in the AWS Networking & Content Delivery blog.

Upvotes: 0

Related Questions