skip to Main Content

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

2

Answers


  1. Chosen as BEST ANSWER

    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


  2. 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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search