Angular Service Worker ngsw-config.json S3 / Cloudflare Image Caching CORS Error

Sep 10 2020

Em um aplicativo Angular 9, quando adiciono este snippet de cache de imagem ao ngsw-config.json, recebo um erro CORS e as imagens não são exibidas. Se eu remover este snippet, o aplicativo funcionará corretamente (sem erros).

O acesso para buscar em 'https://assets.myurl.net/images/banner.jpg' da origem 'https: // localhost: 8100' foi bloqueado pela política CORS: Nenhum cabeçalho 'Access-Control-Allow-Origin' está presente no recurso solicitado. Se uma resposta opaca atender às suas necessidades, defina o modo da solicitação como 'no-cors' para buscar o recurso com o CORS desativado.

ngsw-config.json (snippet):

"assetGroups": [{
    "name": "cdn",
    "installMode": "lazy",
    "updateMode": "lazy",
    "resources": {
        "urls": [
            "https://assets.myurl.net/**"
        ]
    }
}]

As imagens são armazenadas em um intervalo AWS S3 com configuração CORS:

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
</CORSRule>
</CORSConfiguration>
  • O Cloudflare está sendo usado como um CDN (e DNS).
  • O aplicativo está nas versões 9.x mais recentes: @angular 9.2.1, @ angular / service-worker 9.1.12.
  • Adicionar crossorigin = "anonymous" às tags img e picture não pareceu ajudar.

Etapas para reproduzir consistentemente o erro no Chrome / PC:

  1. Limpe o cache do navegador
  2. Abrir navegador privado / anônimo
  3. Vá para o site - as imagens mostram tudo bem
  4. Clique em atualizar - as imagens não são mais exibidas - erros CORS no console do navegador

ATUALIZAR

Com base nesta postagem ( S3 não retorna cabeçalhos Access-Control-Allow-Origin? ), O problema parece ser que o service worker não envia uma Origin no cabeçalho da solicitação (portanto, S3 não envia cabeçalhos de controle de acesso).

Solicitação do Service Worker (copiada do console do Chrome):

Request URL: https://assets.myurl.net/images/banner.jpg
Referrer Policy: strict-origin-when-cross-origin
Provisional headers are shown
Referer: https://localhost:8100/
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36

Em primeiro lugar, certifique-se de que existe um cabeçalho Origin em cada solicitação. Se nenhum cabeçalho Origin for enviado, o S3 não enviará cabeçalhos de controle de acesso, pois o S3 os considera irrelevantes (e normalmente são). Um navegador (para o qual se destina o mecanismo CORS) enviará automaticamente um cabeçalho Origin ao fazer solicitações HTTP de origem cruzada por meio de XMLHTTPRequest.

Com base nesta postagem ( S3 - Access-Control-Allow-Origin Header ), o script S3 cors foi atualizado para incluir:

<AllowedMethod>HEAD</AllowedMethod>
<AllowedHeader>*</AllowedHeader>

Adicionar crossorigin = "anonymous" às tags img não altera o cabeçalho da solicitação do service worker. Portanto, isso não resolve o problema.

O cache do Cloudflare foi removido.

Esta postagem obscura (https://community.cloudflare.com/t/access-control-allow-origin-headers-stripped/158102/2) inclui:

Se você adicionar ou alterar a configuração do CORS no servidor da web de origem, limpar o cache do Cloudflare por URL NÃO atualiza os cabeçalhos do CORS.

Eu armazenei em cache a imagem banner.jpg adicionando uma string de consulta aleatória (ou seja, banner.jpg? Q = abc). A imagem do banner sempre é exibida corretamente (enquanto as outras imagens ainda mostram erros de cor). O cache do service worker na guia Aplicativo do console do Chrome> Armazenamento em cache mostra que a imagem foi armazenada em cache. A configuração de cache do Cloudflare "Nível de cache" = Padrão "fornece um recurso diferente a cada vez que a string de consulta muda".

No entanto, se eu fizer upload de uma nova imagem para S3 banner01.jpg (ou seja, ainda não armazenada em cache pelo Cloudflare), recebo um erro de cors mostrando esta imagem. Tentei fazer isso três vezes adicionais, carregando nomes de imagens diferentes e não obtive um erro de cors. Curiosamente, uma hora depois, até as novas imagens mostram erros de cors.

Um comando curl (que não especifica Origem no cabeçalho) é executado com êxito no meu PC local. A resposta não contém cabeçalhos CORS. por exemplo

curl -v "https://assets.myurl.net/images/banner.jpg"

Adicionar origem ao comando curl retorna cabeçalhos CORS. por exemplo

curl -v --header "Origin: https://www.example.com" "https://assets.myurl.net/images/banner.jpg"

access-control-allow-origin: https://www.example.com
access-control-allow-methods: GET, HEAD
access-control-allow-credentials: true

ATUALIZAÇÃO 2

Não posso explicar por quê, mas o Chrome agora retorna cabeçalhos cors na resposta de busca do Angular Service Worker. A solicitação NÃO inclui um cabeçalho Origin.

accept-ranges: bytes
access-control-allow-methods: GET, HEAD
access-control-allow-origin: *

No entanto, o Safari não. Todos os navegadores parecem estar funcionando bem, mas o Safari ainda mostra erros de cors.

Respostas

LeonGrin Sep 19 2020 at 20:50

Vá para o seu balde S3. Clique em Permissões e, em seguida, em configuração CORS. Se você tiver uma configuração CORS, altere a origem permitida:

<AllowedOrigin>*</AllowedOrigin>

PARA

<AllowedOrigin>http://*</AllowedOrigin>
<AllowedOrigin>https://*</AllowedOrigin>

Se você não tem uma configuração CORS, adicione uma configuração como esta:

<CORSConfiguration>
<CORSRule>
    <AllowedOrigin>http://*</AllowedOrigin>
    <AllowedOrigin>https://*</AllowedOrigin>
    <AllowedMethod>PUT</AllowedMethod>
    <AllowedMethod>POST</AllowedMethod>
    <AllowedMethod>DELETE</AllowedMethod>
    <AllowedMethod>GET</AllowedMethod>
    <AllowedHeader>*</AllowedHeader>
</CORSRule>
<CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
</CORSRule>
</CORSConfiguration>