How do I get CloudFront-Viewer-Country to appear i

2020-07-07 11:02发布

问题:

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.

回答1:

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.



回答2:

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.