Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I get CloudFront-Viewer-Country to appear in response headers?

I am attempting to leverage AWS's geotracking feature on CloudFront to inform my UI of user location so that it knows not to load certain files in problematic regions.

AWS documentation mentions the following but does not give clear instructions on how exactly to configure CloudFront to forward the CloudFront-Viewer-Country header to origin. I need this to work so that requests to my cached objects produce responses with CloudFront-Viewer-Country values.

Configuring CloudFront to Cache Objects Based on the Location of the Viewer

If you want CloudFront to cache different versions of your objects based on the country that the request came from, configure CloudFront to forward the CloudFront-Viewer-Country header to your origin. CloudFront automatically converts the IP address that the request came from into a two-letter country code. For an easy-to-use list of country codes, sortable by code and by country name, see the Wikipedia entry ISO 3166-1 alpha-2.

like image 695
Ben Inada Avatar asked Feb 06 '18 00:02

Ben Inada


People also ask

Does CloudFront have regions?

Amazon CloudFront has multiple globally dispersed Regional Edge Caches (or RECs), providing an additional caching layer close your end-users. They are located between your origin webserver and AWS edge locations that serve content directly to your users.

Is CloudFront regional or global?

Regional edge caches are CloudFront locations that are deployed globally, close to your viewers. They're located between your origin server and the POPs—global edge locations that serve content directly to viewers.

Is CloudFront distribution region specific?

CloudFront is not AWS-region specific. If you overwrite an existing object in a distribution, Cloudfront will not push the new version of the object to an edge location until the object's TTL has been expired and an end user makes a request for the object at that edge location.


2 Answers

CloudFront can't do this by default -- CloudFront-Viewer-Country is intended as a request header, sent to the origin, rather than a response header, sent to the browser.

However... with a Lambda@Edge Origin Response trigger, it is possible to achieve what you appear to be trying to do: echo this header and its value back into the response. Most of the origin request headers that you forward to the origin are also accessible during origin response processing.

“AWS documentation mentions the following but does not give clear instructions on how exactly to configure CloudFront to forward the CloudFront-Viewer-Country header to origin.”

This is done in the Cache Behavior settings, under Cache Based on Selected Request Headers by choosing Whitelist and selecting CloudFront-Viewer-Country in the box on the left and moving it to the box on the right.

You will need to whitelist this header for forwarding to the origin, in order for it to be available to Lambda@Edge -- even if your origin doesn't use or need it -- you still need to forward it for this function to work as intended, because an Origin Request trigger can't see what CloudFront doesn't forward... and most headers are not forwarded unless you whitelist them, including most of the CloudFront-* headers that CloudFront can inject.

'use strict';

exports.handler = (event, context, callback) => {
   const request = event.Records[0].cf.request;
   const response = event.Records[0].cf.response;
   if(request.headers['cloudfront-viewer-country'])
   {
      response.headers['cloudfront-viewer-country'] = request.headers['cloudfront-viewer-country'];
   }
   return callback(null,response);
};

Note that Lambda@Edge requires the outer keys in the header object always to be lowercase, regardless of the actual header lettercase.

like image 90
Michael - sqlbot Avatar answered Oct 18 '22 02:10

Michael - sqlbot


I achieved the same solution with an add_header in my Nginx configuration using the Cloudfront request header.

add_header cloudfront-viewer-country $http_cloudfront_viewer_country;

I figured this would be a cheaper and faster solution.

like image 11
nidal Avatar answered Oct 18 '22 01:10

nidal