Trabalhar com cabeçalhos Range e partNumber
Ao trabalhar com objetos grandes no Amazon S3 Object Lambda, você pode usar o cabeçalho HTTP Range
para baixar um intervalo de bytes especificado de um objeto. É possível usar conexões simultâneas ao Amazon S3 para buscar diferentes escalas de bytes no mesmo objeto. Você também pode usar o parâmetro partNumber
(inteiro entre 1 e 10.000) que executa uma solicitação em um intervalo para a parte especificada do objeto.
Como há várias maneiras pelas quais você pode querer lidar com uma solicitação que inclua os parâmetros Range
ou partNumber
, o S3 Object Lambda não aplica esses parâmetros ao objeto transformado. Em vez disso, sua função do AWS Lambda deve implementar essa funcionalidade conforme necessário para a aplicação.
Para usar os parâmetros Range
e partNumber
com o S3 Object Lambda, faça o seguinte:
-
Ative esses parâmetros na configuração do ponto de acesso do Object Lambda.
-
Escreva uma função do Lambda capaz de lidar com solicitações que incluam esses parâmetros.
As etapas a seguir descrevem como fazer isso.
Etapa 1: configurar o ponto de acesso do Object Lambda
Por padrão, os pontos de acesso do Object Lambda respondem com um erro de código de status HTTP 501 (não implementado) a qualquer solicitação GetObject
ou HeadObject
que contém um parâmetro Range
ou partNumber
nos cabeçalhos ou nos parâmetros de consulta.
Para permitir que um ponto de acesso do Object Lambda aceite essas solicitações, é necessário incluir GetObject-Range
, GetObject-PartNumber
, HeadObject-Range
ou HeadObject-PartNumber
na seção AllowedFeatures
da configuração do ponto de acesso do Object Lambda. Para obter mais informações sobre como atualizar a configuração do ponto de acesso do Object Lambda, consulte Criar pontos de acesso do Object Lambda.
Etapa 2: Implementar o tratamento de Range
ou partNumber
na função do Lambda
Quando o ponto de acesso do Object Lambda invoca a função do Lambda com uma solicitação GetObject
ou HeadObject
em um intervalo, o parâmetro Range
ou partNumber
é incluído no contexto do evento. A localização do parâmetro no contexto do evento depende de qual parâmetro foi usado e de como ele foi incluído na solicitação original para o ponto de acesso do Object Lambda, conforme explicado na tabela a seguir.
Parameter | Localização do contexto do evento |
---|---|
|
|
|
|
|
|
Importante
O URL pré-assinado fornecido para o ponto de acesso do Object Lambda não contém o parâmetro Range
ou partNumber
da solicitação original. Veja as opções a seguir sobre como lidar com esses parâmetros na função do AWS Lambda.
Depois de extrair o valor Range
ou partNumber
, você poderá adotar uma das seguintes abordagens com base nas necessidades da aplicação:
-
Mapear o
Range
oupartNumber
solicitado para o objeto transformado (recomendado).O jeito mais confiável de lidar com solicitações
Range
epartNumber
é fazer o seguinte:-
Recupere o objeto completo do Amazon S3.
-
Transforme o objeto.
-
Aplique os parâmetros
Range
oupartNumber
solicitados ao objeto transformado.
Para fazer isso, use o URL pré-assinado fornecido para buscar todo o objeto do Amazon S3 e, em seguida, processe o objeto conforme necessário. Para obter um exemplo de função do Lambda que processa o parâmetro
Range
dessa forma, consulte este exemplono repositório de exemplos da AWS no GitHub. -
-
Associe o
Range
solicitado ao URL pré-assinado.Em alguns casos, a função do Lambda pode associar o
Range
solicitado diretamente ao URL pré-assinado para recuperar apenas parte do objeto do Amazon S3. Essa abordagem será apropriada somente se sua transformação atender a ambos os seguintes critérios:-
Sua função de transformação pode ser aplicada a intervalos de objetos parciais.
-
Aplicar o parâmetro
Range
antes ou depois da função de transformação ocasiona a transformação do mesmo objeto.
Por exemplo, uma função de transformação que converte todos os caracteres em um objeto codificado em ASCII em maiúsculas atende a ambos os critérios anteriores. A transformação pode ser aplicada a parte de um objeto, e aplicar o parâmetro
Range
ou antes da transformação produz o mesmo resultado que a aplicação do parâmetro após a transformação.Por outro lado, uma função que inverte os caracteres em um objeto codificado em ASCII não atende a esses critérios. Essa função atende ao critério 1, pois pode ser aplicada a intervalos de objetos parciais. No entanto, ela não atende ao critério 2, porque aplicar o parâmetro
Range
antes da transformação produz resultados diferentes do que a aplicação do parâmetro após a transformação.Pense em uma solicitação para aplicar a função aos três primeiros caracteres de um objeto com o conteúdo
abcdefg
. Aplicar o parâmetroRange
antes da transformação recupera somenteabc
e, em seguida, reverte os dados, retornandocba
. Mas se o parâmetro for aplicado após a transformação, a função recuperará todo o objeto, o reverterá e, em seguida, aplicará o parâmetroRange
, retornandogfe
. Como esses resultados são diferentes, essa função não deve aplicar o parâmetroRange
ao recuperar o objeto do Amazon S3. Em vez disso, ela deve recuperar todo o objeto, executar a transformação e, somente então, aplicar o parâmetroRange
.Atenção
Em muitos casos, aplicar o parâmetro
Range
ao URL pré-assinado resultará em um comportamento inesperado da função do Lambda ou do cliente solicitante. A menos que você tenha certeza de que seu aplicativo funcionará corretamente ao recuperar apenas um objeto parcial do Amazon S3, recomendamos recuperar e transformar objetos completos, conforme descrito anteriormente na abordagem A.Se a aplicação atender aos critérios descritos anteriormente na abordagem B, você poderá simplificar a função do AWS Lambda buscando apenas o intervalo de objetos solicitado e executando a transformação nesse intervalo.
O exemplo de código Java a seguir demonstra como fazer o seguinte:
-
Recuperar o cabeçalho
Range
da solicitaçãoGetObject
. -
Adicionar o cabeçalho
Range
ao URL pré-assinado que o Lambda pode usar para recuperar o intervalo solicitado do Amazon S3.
private HttpRequest.Builder applyRangeHeader(ObjectLambdaEvent event, HttpRequest.Builder presignedRequest) { var header = event.getUserRequest().getHeaders().entrySet().stream() .filter(e -> e.getKey().toLowerCase(Locale.ROOT).equals("range")) .findFirst(); // Add check in the query string itself. header.ifPresent(entry -> presignedRequest.header(entry.getKey(), entry.getValue())); return presignedRequest; }
-