Como mapear subdomínio no CloudFront para o mesmo nome no S3?

Como mapear subdomínio no CloudFront para o mesmo nome no S3?

Tenho procurado uma maneira de fazer o seguinte, se alguém puder me esclarecer, ficaria muito grato.

por exemplo, os seguintes mapeamentos seriam possíveis em uma única instância do CloudFront?

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

e assim por diante..

O caso de uso é que eu quero ser capaz de implantar tantos ambientes para cada ramificação git que mapeia para um bucket existente no S3. Tudo isso seria possível?

Responder1

Sim, é possível, mas você precisará usar o aprimoramento do Lambda@Edge no CloudFront para manipular os parâmetros da solicitação antes de enviar a solicitação ao bucket.

Descrevi uma solução possível emesta postagem oficial do fórum. Essa mesma solução está incluída abaixo.

O Lambda@Edge permite acesso programático às solicitações ou respostas HTTP à medida que o CloudFront as processa, fornecendo essencialmente ganchos de gatilho. A transação HTTP é apresentada como um objeto javascript que você pode observar e modificar e depois retornar o controle ao CloudFront.

Para este aplicativo, você precisa usar o endpoint de hospedagem do site do bucket como seu nome de domínio de origem na configuração do CloudFront (ou seja, não selecione o bucket no menu suspenso - digite-o usando o nome de host "s3-website" apropriado ) e você precisa colocar o Hostcabeçalho na lista de permissões para encaminhá-lo para a origem, mesmo que na verdade não o encaminhemos (iremos lê-lo e depois manipulá-lo, junto com o caminho) e mesmo que, normalmente, encaminhe isso para uma origem S3 não funcionaria como esperado... mas precisamos dizer ao CloudFront para colocá-la na lista de permissões para que possa ser lida e manipulada.

Configure a seguinte função Lambda como gatilho de solicitação de origem. Esse gatilho é acionado depois que o cache do CloudFront é verificado e ocorre uma falha no cache, e antes que a solicitação seja enviada ao servidor de origem (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);
};

Lembre-se também de definir seuerro de cache TTL mínimo para 0para evitar respostas de erro de cache do CloudFront. Esta é uma configuração separada de min/default/max TTL nas configurações de comportamento do cache. O padrão é 5 minutos, o que faz sentido, mas complica a solução de problemas se você não antecipar esse comportamento.


Observe que as funções do Lambda@Edge agora podem usar a versão 6.10 ouv8.10Ambiente de execução Node.js. O exemplo acima foi escrito originalmente para v6.10, mas é compatível com qualquer um dos tempos de execução porque na v8.10 o manipulador tem mais opções: ele pode usar async/await, pode retornar uma promessa diretamente ou pode ser escrito como mostrado acima para usar a interface de retorno de chamada.

informação relacionada