CloudFront игнорирует пользовательский источник, предоставленный Lambda @ Edge - PullRequest
0 голосов
/ 31 марта 2019

Я пытаюсь настроить CloudFront , чтобы он извлекал содержимое из S3 или из внешнего источника в зависимости от значения заголовка .

Для этого я реализовал Lambda @ Edge , который запускается при событии Origin Request . меняет источник на пользовательский , но CloudFront каким-то образом все еще обращается к содержимому S3 .

Это функция Lambda:

'use strict';

const PRERENDER_HOST = 'xxxxx.ngrok.io'
const IS_SSL = false

exports.handler = (event, context, callback) => {
    console.log('event', JSON.stringify(event))
    const request = event.Records[0].cf.request;
    const headers = request.headers;
    const should_prerender = headers['x-should-prerender'] 
            ? JSON.parse(headers['x-should-prerender'][0].value)
            : false

    console.log('should prerender', should_prerender, 'existed', !!headers['x-should-prerender'])
    console.log('uri is', request.uri)
    if (should_prerender) {
        set_header('host', PRERENDER_HOST, headers)
        request.origin = {
            custom: {
                domainName: PRERENDER_HOST,
                port: IS_SSL ? 443 : 80,
                protocol: IS_SSL ? 'https' : 'http',
                readTimeout: 20,
                keepaliveTimeout: 5,
                customHeaders: {},
                path: request.uri,
                sslProtocols: ['TLSv1', 'TLSv1.1'],
            }
        }
    }

    console.log('request', JSON.stringify(request))

    callback(null, request)

    function set_header(name, value, store) {
        store[name.toLowerCase()] = [
            {
                key: name,
                value
            }
        ]
    }
};

Затем я вставляю содержимое request, которое передается в callback.Это было извлечено из соответствующего журнала CloudWatch.Журнал показывает, как источник установлен к пользовательскому.

{
   "uri" : "/index.html",
   "origin" : {
      "custom" : {
         "sslProtocols" : [
            "TLSv1",
            "TLSv1.1"
         ],
         "keepaliveTimeout" : 5,
         "port" : 80,
         "domainName" : "xxxxx.ngrok.io",
         "path" : "/index.html",
         "customHeaders" : {},
         "readTimeout" : 20,
         "protocol" : "http"
      }
   },
   "headers" : {
      "x-should-prerender" : [
         {
            "key" : "x-should-prerender",
            "value" : "true"
         }
      ],
      "host" : [
         {
            "key" : "host",
            "value" : "xxxxx.ngrok.io"
         }
      ],
      "upgrade-insecure-requests" : [
         {
            "value" : "1",
            "key" : "Upgrade-Insecure-Requests"
         }
      ],
      "dnt" : [
         {
            "key" : "DNT",
            "value" : "1"
         }
      ],
      "x-forwarded-for" : [
         {
            "key" : "X-Forwarded-For",
            "value" : "xxx.xxx.xx.xx"
         }
      ],
      "via" : [
         {
            "value" : "1.1 25xxxxxbcxxxx07847a7xxxxxx.cloudfront.net (CloudFront)",
            "key" : "Via"
         }
      ],
      "user-agent" : [
         {
            "key" : "User-Agent",
            "value" : "Amazon CloudFront"
         }
      ],
      "accept-encoding" : [
         {
            "key" : "Accept-Encoding",
            "value" : "gzip"
         }
      ]
   },
   "clientIp" : "xxx.xx.xx.xxx",
   "querystring" : "",
   "method" : "GET"
}

Есть идеи о том, что здесь может происходить?

ОБНОВЛЕНИЕ 1 : После попытки с https все заработало.Тем не менее, понятия не имею, почему он не работает с http. ОБНОВЛЕНИЕ 2 : Исправление ошибки.Я написал View Request вместо Origin Request.Спасибо Майклу за то, что заметил.

1 Ответ

1 голос
/ 31 марта 2019

Триггеры Viewer Request запускаются на "передней стороне" CloudFront - стороне просмотра - перед проверкой кэша.

Источник «известен» в тот момент, потому что сопоставление Поведения Кэша уже произошло, но вы не можете влиять на выбор источника на стороне зрителя, потому что CloudFront технически не решил, стоит ли вообще связываться с источником, пока .

Изменения в исходном сервере могут быть сделаны только на исходной стороне (обратной стороне, после проверки кэша) CloudFront, в триггере исходного запроса. Для триггера запроса средства просмотра не имеет смысла изменять источник, поскольку источник не является частью ключа кэша, поэтому, если триггер запроса средства просмотра изменяет источник, кэш будет затем проверяться без каких-либо согласований для изменилось происхождение, поэтому кэшированные ответы не могут быть уверены, что они даже пришли из правильного места.

Вам понадобится использовать триггер исходного запроса, и вам потребуется белый список x-should-prerender для пересылки к источнику (в настройках поведения кэша), чтобы триггер мог его видеть. Если вы не хотите, чтобы источник действительно его видел, вам нужно будет использовать код триггера для его удаления, но он должен быть в белом списке, чтобы его мог увидеть триггер Origin Request.

Если вы хотите, чтобы функция изменила запрос таким образом, чтобы он влиял на ответ от источника, используйте событие запроса источника.

https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-how-to-choose-event.html

...