Назад | Перейти на главную страницу

Как сопоставить субдомен в CloudFront с тем же именем в S3?

Я искал способ сделать следующее, если кто-то может просветить меня, будет очень признателен.

например возможны ли следующие сопоставления в одном экземпляре CloudFront?

feature-a.domain.com => dev-bucket/feature-a
feature-b.domain.com => dev-bucket/feature-b
staging.domain.com   => dev-bucket/staging

и так далее..

Вариант использования: я хочу иметь возможность развертывать столько сред для каждой ветки git, которая соответствует существующей корзине на S3. Возможно ли все это?

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

Я описал одно возможное решение в это официальное сообщение на форуме. То же решение включено ниже.

Lambda @ Edge обеспечивает программный доступ к HTTP-запросам или ответам по мере их обработки CloudFront - по сути, обеспечивая триггерные перехватчики. Транзакция HTTP представлена ​​как объект javascript, который вы можете наблюдать и изменять, а затем возвращать управление CloudFront.

Для этого приложения вам необходимо использовать конечную точку хоста корзины в качестве исходного доменного имени в конфигурации CloudFront (т.е. не выбирайте сегмент в раскрывающемся списке - введите его, используя соответствующее имя хоста "s3-website" ) и вам нужно внести в белый список Host заголовок для пересылки в источник, даже если мы на самом деле не будем его пересылать (мы будем его читать, а затем манипулировать им вместе с путем), и хотя, как правило, пересылка этого источника в S3 не будет работать как предназначено ... но мы должны указать CloudFront внести его в белый список, чтобы его можно было читать и изменять.

Настройте следующую лямбда-функцию в качестве триггера запроса источника. Этот триггер срабатывает после проверки кеша CloudFront и промаха кэша, а также до отправки запроса на исходный сервер (S3).

'use strict';

// https://serverfault.com/a/930191/153161
// if the end of incoming Host header matches this string, 
// strip this part and prepend the remaining characters onto the request path,
// along with a new leading slash (otherwise, the request will be handled
// with an unmodified path, at the root of the bucket)

// set this to what we should remove from the incoming hostname, including the leading dot.

const remove_suffix = '.example.com';

// provide the correct origin hostname here so that we send the correct 
// Host header to the S3 website endpoint
// this is the same value as "origin domain name" in the cloudfront distribution configuration

const origin_hostname = 'example-bucket.s3-website-us-east-1.amazonaws.com';

exports.handler = (event, context, callback) => {
  const request = event.Records[0].cf.request;
  const headers = request.headers;
  const host_header = headers.host[0].value;

  if(host_header.endsWith(remove_suffix))
  {
    // prepend '/' + the subdomain onto the existing request path ("uri")
    request.uri = '/' + host_header.substring(0,host_header.length - remove_suffix.length) + request.uri;
  }

  // fix the host header so that S3 understands the request
  // we have to do this even if the above if() didn't match
  headers.host[0].value = origin_hostname;

  // return control to CloudFront with the modified request
  return callback(null,request);
};

Не забудьте также установить ошибка кеширования минимального TTL до 0 во избежание получения ответов об ошибках кеширования CloudFront. Это отдельная настройка от минимального / стандартного / максимального TTL в настройках Cache Behavior. По умолчанию это 5 минут, что имеет смысл, но усложняет устранение неполадок, если вы не ожидаете такого поведения.


Обратите внимание, что функции Lambda @ Edge теперь могут использовать либо v6.10, либо v8.10 Среда выполнения Node.js. Приведенный выше пример изначально был написан для версии 6.10, но он совместим с любой средой выполнения, поскольку в версии 8.10 обработчик имеет больше возможностей: он может использовать async / await, он может напрямую возвращать обещание или может быть написан, как показано выше. использовать интерфейс обратного вызова.