Que limitações se aplicam a respostas opacas?

86

As respostas opacas são definidas como parte da API Fetch e representam o resultado de uma solicitação feita a uma origem remota quando o CORS não está ativado.

Que limitações práticas e "pegadinhas" existem em torno de como as respostas opacas podem ser usadas, tanto do JavaScript quanto como recursos em uma página?

Jeff Posnick
fonte

Respostas:

125

Acesso aos cabeçalhos / corpo das respostas opacas

A limitação mais direta em torno de respostas opacas é que você não pode obter informações significativas de volta da maioria das propriedades da Responseclasse, como headers, ou chamar os vários métodos que compõem a Bodyinterface, como json()ou text(). Isso está de acordo com a natureza de caixa preta de uma resposta opaca.

Usando respostas opacas como recursos em uma página

As respostas opacas podem ser usadas como um recurso em uma página da web sempre que o navegador permitir que um recurso de origem cruzada não CORS seja usado. Aqui está um subconjunto de elementos para os quais recursos de origem cruzada não CORS e, portanto, respostas opacas, são válidos, adaptado da documentação da Mozilla Developer Network :

  • <script>
  • <link rel="stylesheet">
  • <img>,, <video>e<audio>
  • <object> e <embed>
  • <iframe>

Um caso de uso notável para o qual as respostas opacas não são válidas é para recursos de fonte .

Em geral, para determinar se você pode usar uma resposta opaca como um tipo específico de recurso em uma página, verifique a especificação relevante. Por exemplo, a especificação HTML explica que respostas de origem cruzada não CORS (ou seja, opacas) podem ser usadas para <script>elementos, embora com algumas limitações para evitar o vazamento de informações de erro.

Respostas opacas e API de armazenamento em cache

Uma "pegadinha" que o desenvolvedor pode encontrar com respostas opacas envolve o uso delas com a API Cache Storage . Duas informações básicas são relevantes:

  • A statuspropriedade de uma resposta opaca é sempre definida como0 , independentemente de a solicitação original ter sido bem-sucedida ou não.
  • Os métodos add()/ da API de armazenamento em cache addAll()rejeitarão se as respostas resultantes de qualquer uma das solicitações tiverem um código de status que não esteja no intervalo 2XX .

Destes dois pontos, segue-se que, se a solicitação executada como parte da chamada add()/ addAll()resultar em uma resposta opaca, ela não será adicionada ao cache.

Você pode contornar isso executando explicitamente um fetch()e, em seguida, chamando o put()método com a resposta opaca. Ao fazer isso, você está efetivamente optando pelo risco de que a resposta que está armazenando em cache possa ter sido um erro retornado por seu servidor.

const request = new Request('https://third-party-no-cors.com/', {mode: 'no-cors'});
// Assume `cache` is an open instance of the Cache class.
fetch(request).then(response => cache.put(request, response));

Respostas opacas e API navigator.storage

Para evitar o vazamento de informações entre domínios, há um preenchimento significativo adicionado ao tamanho de uma resposta opaca usada para calcular os limites de cota de armazenamento (ou seja, se uma QuotaExceededexceção é lançada) e relatado pela navigator.storageAPI .

Os detalhes desse preenchimento variam de navegador para navegador, mas para o Google Chrome, isso significa que o tamanho mínimo que qualquer resposta opaca em cache contribui para o uso geral do armazenamento é de aproximadamente 7 megabytes . Você deve ter isso em mente ao determinar quantas respostas opacas você deseja armazenar em cache, uma vez que você pode facilmente exceder as limitações de cota de armazenamento muito mais cedo do que você esperaria com base no tamanho real dos recursos opacos.

Jeff Posnick
fonte
1
Na verdade, ele não ocupa essa quantidade de espaço no armazenamento físico de um dispositivo. É apenas o valor que contribui para os cálculos da cota.
Jeff Posnick
1
Sua resposta é até mesmo mencionada no guia Workbox aqui: developers.google.com/web/tools/workbox/guides/…
Dima Slivin
14
Verdade, mas eu escrevi aquele guia Workbox :-)
Jeff Posnick
1
Isso torna o uso de um CDN de imagem em conjunto com esse tipo de cache um projeto ruim? (Desperdiçando espaço alocado) É possível armazenar em cache um arquivo recuperado de nosso domínio principal e expô-lo com o link CDN (chave)? Por exemplo, posso fazer com que uma solicitação de rede vá para cdn.x.com/test.jpge as solicitações de cache para o domínio principal www.x.com/test.jpg.
cglacet
1
Encontrei um truque em torno desse problema, não tenho ideia se essa é uma solução decente, mas basicamente faço meu service worker fingir que é o CDN. Eu adiciono URLs relativos ao domínio no cache (por exemplo, /test.jpgentão para cada solicitação de busca para cdn.x.com/test.jpgeu modificar o URL com o domínio de origem (o URL se torna www.x.com/test.jpg), eu uso algo assim:. const cacheUrl = (url.hostname == 'cdn.x.com')? new URL(event.target.location.origin + url.pathname): url;Eu então solicito o cache com este novo url caches.match(cacheUrl), que parece para funcionar bem. Alguma abordagem?
cglacet