Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

accessing origin URL from AWS lambda@edge

I'm trying to implement a "proxy" to multiple websites using lambda@edge 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)

lambda@edge function: defined as origin-request

My lambda@edge 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 lambda@edge 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

like image 968
Ozzz123 Avatar asked Dec 14 '17 15:12

Ozzz123


People also ask

How can I change the origin of a Lambda request?

A Lambda function that is called for each request that can change what is sent to the origin makes this possible. Before CloudFront sends the request to S3 for a request to /app1/index.html, the function can cut the first part and make it go to /index.html. In effect, you can separate the origin request path from the cache behavior path pattern.

How do I rewrite a URL in lambda?

Rewriting URLs with Lambda@Edge Lambda@Edge is a CloudFront feature that lets you run code out at “the edge”, meaning wherever CloudFront’s CDN is caching your content globally. Within your Lambda functions, you can manipulate requests and responses. This is perfect for doing URL rewriting for a single-page app.

How does Amazon CloudFront work with lambda@edge?

Amazon CloudFront routes the request to the nearest AWS edge location. The CloudFront distribution’s private behavior is configured to launch a Lambda@Edge function on ViewerRequest event. Lambda@Edge decodes the JWT and checks if the user belongs to the correct Cognito User Pool.

How to create HTTP APIs for a lambda function?

With the launch of Lambda Function URL you can create HTTP APIs for a Lambda Function quickly. The architecture is simple and straight forward with CloudFront connecting to the Lambda Function URL as origin. When you create a Lambda Function URL, a unique URL endpoint is assigned in the format shown below


1 Answers

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 L@E and origin-request L@E.

In the viewer request L@E 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);
}
like image 131
Sriraghavan Subramanian Avatar answered Nov 08 '22 09:11

Sriraghavan Subramanian