59 votes

Chrome S3 Cloudfront: Pas d'en-tête 'Access-Control-Allow-Origin' sur la demande XHR initiale

J'ai une page web (https://smartystreets.com/contact) qui utilise jQuery pour charger des fichiers SVG depuis S3 via le CDN CloudFront.

Dans Chrome, j'ouvrirai une fenêtre Incognito ainsi que la console. Ensuite, je chargerai la page. Au fur et à mesure que la page se charge, j'obtiendrai généralement 6 à 8 messages dans la console qui ressemblent à ceci :

XMLHttpRequest cannot load 
https://d79i1fxsrar4t.cloudfront.net/assets/img/feature-icons/documentation.08e71af6.svg.
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'https://smartystreets.com' is therefore not allowed access.

Si je fais un rechargement standard de la page, même plusieurs fois, je continue à obtenir les mêmes erreurs. Si je fais Command+Shift+R, alors la plupart, et parfois toutes, les images se chargeront sans l'erreur XMLHttpRequest.

Parfois, même après le chargement des images, si je rafraîchis la page, une ou plusieurs des images ne se chargeront pas et renverront à nouveau cette erreur XMLHttpRequest.

J'ai vérifié, modifié et revérifié les paramètres sur S3 et Cloudfront. Dans S3, ma configuration CORS ressemble à ceci :

    *
    http://*
    https://*
    GET
    3000
    Authorization

(Remarque : initialement, j'avais seulement *, même problème.)

Dans CloudFront, le comportement de la distribution est configuré pour autoriser les méthodes HTTP : GET, HEAD, OPTIONS. Les méthodes mises en cache sont les mêmes. Les entêtes transmis sont configurés sur "Whitelist" et cette liste blanche inclut "Access-Control-Request-Headers, Access-Control-Request-Method, Origin".

Le fait que cela fonctionne après un rechargement du navigateur sans mise en cache semble indiquer que tout va bien du côté de S3/CloudFront, sinon pourquoi le contenu serait-il livré. Mais alors pourquoi le contenu ne serait-il pas livré lors de la consultation initiale de la page ?

Je travaille sur Google Chrome sous macOS. Firefox n'a aucun problème à récupérer les fichiers à chaque fois. Opera NE récupère JAMAIS les fichiers. Safari récupérera les images après plusieurs rafraîchissements.

En utilisant curl je n'ai aucun problème :

curl -I -H 'Origin: smartystreets.com' https://d79i1fxsrar4t.cloudfront.net/assets/img/phone-icon-outline.dc7e4079.svg

HTTP/1.1 200 OK
Content-Type: image/svg+xml
Content-Length: 508
Connection: keep-alive
Date: Tue, 20 Jun 2017 17:35:57 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET
Access-Control-Max-Age: 3000
Last-Modified: Thu, 15 Jun 2017 16:02:19 GMT
ETag: "dc7e4079f937e83291f2174853adb564"
Cache-Control: max-age=31536000
Expires: Wed, 01 Jan 2020 23:59:59 GMT
Accept-Ranges: bytes
Server: AmazonS3
Vary: Origin,Access-Control-Request-Headers,Access-Control-Request-Method
Age: 4373
X-Cache: Hit from cloudfront
Via: 1.1 09fc52f58485a5da8e63d1ea27596895.cloudfront.net (CloudFront)
X-Amz-Cf-Id: wxn_m9meR6yPoyyvj1R7x83pBDPJy1nT7kdMv1aMwXVtHCunT9OC9g==

Certains ont suggéré que je supprime la distribution CloudFront et la recrée. Cela semble être une solution assez radicale et inconfortable.

Quelle est la cause de ce problème ?

Mise à jour :

Ajout des en-têtes de réponse d'une image qui n'a pas pu se charger.

age:1709
cache-control:max-age=31536000
content-encoding:gzip
content-type:image/svg+xml
date:Tue, 20 Jun 2017 17:27:17 GMT
expires:2020-01-01T23:59:59.999Z
last-modified:Tue, 11 Apr 2017 18:17:41 GMT
server:AmazonS3
status:200
vary:Accept-Encoding
via:1.1 022c901b294fedd7074704d46fce9819.cloudfront.net (CloudFront)
x-amz-cf-id:i0PfeopzJdwhPAKoHpbCTUj1JOMXv4TaBgo7wrQ3TW9Kq_4Bx0k_pQ==
x-cache:Hit from cloudfront

0 votes

Vous avez raison - supprimer et recréer est extrême et ne devrait tout simplement jamais être nécessaire. Pouvez-vous nous montrer les en-têtes de requête et de réponse du navigateur pour une requête échouée ? Et peut-être pour une requête réussie du même objet exact ?

0 votes

@Michael-sqlbot, j'espérais un peu que vous visitiez l'URL (smartystreets.com/contact) et voyiez si la même chose se produisait sur votre machine. :) La chose intéressante à propos des erreurs est qu'en dehors de l'erreur dans la console, le navigateur signale un statut de 200, indiquant qu'il utilise l'image "(du cache disque)", ce qui ne devrait pas être possible avec l'Incognito, je pensais. Même après avoir vidé le cache local.

1 votes

Oui, les gens "inventent" si souvent des noms de domaine (qui s'avèrent être de vrais sites, mais pas le site en question) que je n'ai pas réalisé au départ que vous aviez donné le lien réel et correct vers votre site. Merci pour cela, vous pouvez ignorer ma demande. Je peux reproduire le problème. Cela semble être un problème du côté du client. Je suis en train d'explorer une théorie.

0voto

Tom Kelsey Points 1

Je n'avais pas la réputation pour commenter la réponse acceptée mais je voulais aider quiconque rencontre des problèmes similaires.

En bref, je crois qu'AWS a changé quelque chose pour que le code lambda de la solution acceptée ne fonctionne plus (peut-être si/quand vous passez à la nouvelle implémentation des politiques de cache de CloudFront?)

headers['vary'] n'est pas falsy donc le contournement n'est jamais déclenché.

C'est le lambda corrigé selon la solution de dobesv dans le post original du forum ( https://forums.aws.amazon.com/thread.jspa?messageID=796312):

'use strict';

// Si la réponse manque d'un en-tête Vary:, corrigez-le dans un déclencheur de réponse d'origine CloudFront.

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

    if(!headers.vary) headers.vary = [];
    for(const hdr of ['Origin', 'Access-Control-Request-Headers', 'Access-Control-Request-Method']) {
        if(!headers['vary'].some(h => h.value === hdr)) {
            headers.vary.push({key: 'Vary', value: hdr});
        }
    }
    callback(null, response);
};

0voto

dmB Points 1

Pour éviter le comportement de mise en cache, vous pouvez ajouter un paramètre de requête aléatoire lors de la demande via XHR.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X