accessing origin URL from AWS [email protected]

I’m trying to implement a “proxy” to multiple websites using [email protected] on AWS Cloudfront.

My setup is roughly:

DNS: *.domain.com -> some_uuid.cloudfront.net (Cloudfront distribution)

Cloudfront: some_uuid.cloudfront.net -> s3 bucket origin

s3 bucket: websites/ (a folder that contains multiple websites)

[email protected] function: defined as origin-request

My [email protected] function is quite simple:

  1. check if the website resource exists in the s3 bucket.

  2. if it does, change the request uri to the resource s3 url.

  3. if not, send a request to a backend server to render the resource, store on s3 and return it.

I’m having trouble getting the origin domain of the website. For example, if I try to access “my_website.domain.com” – in my lambda function i don’t have this domain info from the request.

I think I can implement another [email protected] function as viewer request to pass the domain as a header, but if I can, I prefer to avoid that.

Is there any other solution?

Thanks

Here is Solutions:

We have many solutions to this problem, But we recommend you to use the first solution because it is tested & true solution that will 100% work for you.

Solution 1

The primary problem here is that Cloudfront overwrites the host header in the request to the origin host.
I was able to workaround this by using a combination of viewer-request [email protected] and origin-request [email protected]

In the viewer request [email protected] copy the host header into another header like x-forwarded-host.

// viewer-request.js
exports.handler = (event, context, callback) => {
    const request = event.Records[0].cf.request
    request.headers['x-forwarded-host'] = [
      { key: 'X-Forwarded-Host', value: request.headers.host[0].value }
    ]
    return callback(null, request)
}

Configure your cloudfront to whitelist x-forwarded-host host header in the behaviour.
This way the Cloudfront also takes into consideration the x-forwarded-host when caching and also passes the header along to the origin-request lambda.

So now in your origin-request lambda you can access the x-forwarded-host header

// origin-request.js
exports.handler = (event, context, callback) => {
    const request = event.Records[0].cf.request;
    const headers = request.headers;
    const requestHost = headers['x-forwarded-host'][0].value;
    console.log(requestHost);
    callback(null, request);
}

Solution 2

So the problem with your use case is that the value of the host header exposed to your origin-request [email protected] function is the domain name of the s3 bucket, and not the original host header CloudFront has received from a viewer, correct?

In order to see the original Host header CloudFront received from the viewer, you need to whitelist it. However, CloudFront currently doesn’t allow to whitelist headers for s3 origins. This is a bug/limitation that should be fixed by CloudFront. There is a workaround though. If the s3 bucket is publicly accessible (i.e. you are not using origin access identity), you can configure your S3 origin as a custom origin using a website endpoint like mybucket.s3-website-us-east-1.amazonaws.com. Then, you will be able to whitelist the host header and see the domain name of your website as requested by the viewer. You can then modify the origin request according to your use case. Don’t forget also to change the host header back to the s3 endpoint so that S3 would accept the request.

Note: Use and implement solution 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply