Политика CORS для кэшированного образа

В Chrome 22 и Safari 6.

Загрузка изображений из s3 для использования на холсте (с извлечением в качестве основного намерения) с использованием корзины S3 с поддержкой CORS со следующим кодом:

<!-- In the html -->
<img src="http://s3....../bob.jpg" /> 

// In the javascript, executed after the dom is rendered
this.img = new Image();
this.img.crossOrigin = 'anonymous';
this.img.src = "http://s3....../bob.jpg";

Я заметил следующее:

  1. Отключить кеши
  2. Все отлично работает, оба изображения загружаются

Затем попробуйте с включенными кешами:

  1. Включить кеши
  2. Загрузка изображения DOM, изображение canvas создает исключение безопасности dom

Если я изменю часть кода javascript для добавления строки запроса, вот так:

this.img = new Image();
this.img.crossOrigin = 'anonymous';
this.img.src = "http://s3....../bob.jpg?_";

Все работает, даже если кэширование включено полностью. Я столкнулся с проблемой кеширования, используя http-прокси и наблюдая, что в случае сбоя изображение на самом деле не запрашивается с сервера.

Вывод, который я вынужден сделать, заключается в том, что кэш изображений сохраняет исходные заголовки запроса, которые затем используются для последующего запроса с поддержкой CORS, и генерируется исключение безопасности из-за нарушения той же политики происхождения.

Это намеренное поведение?

Редактировать: Работает в Firefox.

Edit2: политика Cors в корзине s3

<?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>

Я использую широко открытые, потому что сейчас я просто тестирую из своей локальной коробки. Это еще не в производстве.

Edit3: обновлена ​​политика Cors для указания источника

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
        <AllowedOrigin>http://localhost:5000</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
    </CORSRule>
</CORSConfiguration>

Проверенные исходящие заголовки:

Origin  http://localhost:5000
Accept  */*
Referer http://localhost:5000/builder
Accept-Encoding gzip,deflate,sdch
Accept-Language en-US,en;q=0.8
Accept-Charset  ISO-8859-1,utf-8;q=0.7,*;q=0.3

Входящие заголовки:

Access-Control-Allow-Origin http://localhost:5000
Access-Control-Allow-Methods    GET
Access-Control-Allow-Credentials    true

По-прежнему происходит сбой в Chrome, если я не удаляю кеш при загрузке на холст.

Изменить 4:

Просто заметил это в случае неудачи.

Исходящие заголовки:

GET /373c88b12c7ba7c513081c333d914e8cbd2cf318b713d5fb993ec1e7 HTTP/1.1
Host    amir.s3.amazonaws.com
User-Agent  Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.91 Safari/537.4
Accept  */*
Referer http://localhost:5000/builder
Accept-Encoding gzip,deflate,sdch
Accept-Language en-US,en;q=0.8
Accept-Charset  ISO-8859-1,utf-8;q=0.7,*;q=0.3
If-None-Match   "99c958e2196c60aa8db385b4be562a92"
If-Modified-Since   Sat, 29 Sep 2012 13:53:34 GMT

Входящие заголовки:

HTTP/1.1 304 Not Modified
x-amz-id-2  3bzllzox/vZPGSn45Y21/vh1Gm/GiCEoIWdDxbhlfXAD7kWIhMKqiSEVG/Q5HqQi
x-amz-request-id    48DBC4559B5B840D
Date    Sat, 29 Sep 2012 13:55:21 GMT
Last-Modified   Sat, 29 Sep 2012 13:53:34 GMT
ETag    "99c958e2196c60aa8db385b4be562a92"
Server  AmazonS3

Я думаю, что это первый запрос, вызванный домом. Я не знаю, что это не запрос javascript, хотя.

4 ответа

Проблема в том, что изображение кэшируется из предыдущего запроса, без обязательных заголовков CORS. Таким образом, когда вы запрашиваете его снова, для холста с указанным 'crossorigin', браузер использует кэшированную версию, не видит необходимые заголовки, и вызывает ошибку CORS. Когда вы добавляете '?_' В URL, браузер игнорирует кеш, так как это другой URL. Посмотрите на эту ветку: https://bugs.chromium.org/p/chromium/issues/detail?id=409090

Firefox и другие браузеры не имеют такой проблемы.

Описанное поведение кажется логичным, поскольку ключ записи в кэш является целевым URI (см. 7234 Протокол передачи гипертекста (HTTP/1.1): Кэширование). Чтобы решить эту проблему и эффективно использовать кэш, необходимо, чтобы сервер размещения изображений давал одинаковый ответ в обоих случаях.

Один из вариантов - заставить агента пользователя отправлять Origin HTTP-заголовок также в первом запросе (учитывая, что ответ с ключом targetUri уже не в кеше)

<img src="targetUri" crossorigin="anonymous" />

Другой вариант - настроить сервер размещения изображений для отправки HTTP-заголовков, связанных с CORS, независимо от того, содержит ли запрос Origin HTTP заголовок. Для получения дополнительной информации см. S3 CORS, всегда присылайте Vary: Origin обсуждение Stackru.

Также вы можете сообщить пользовательскому агенту, что ответы чувствительны к Origin HTTP-заголовок запроса с использованием Vary HTTP-заголовок ответа. Недостатком является то, что, вероятно, пользовательский агент будет использовать Vary заголовок только как средство проверки ответа (а не как часть ключа входа в кэш) и хранит только один экземпляр ответа для целевого URI, что затрудняет эффективное использование кеша. Для получения дополнительной информации проверьте Состояние Кэширования Браузера, Пересмотренная статья Марком Ноттингемом.

У меня была очень похожая проблема, и я решил ее, добавив следующий заголовок в ответ от сервера.

'Vary': 'Origin'

После добавления заголовка все мои запросы были кэшированы.

Какие настройки CORS вы используете? Этот пост предполагает, что подстановочные знаки в AllowedOrigin анализируются (а не передаются дословно, это выглядит как недокументированное поведение); и Access-Control-Allow-Origin Значение заголовка затем кэшируется для последующих запросов, вызывая проблемы, аналогичные тем, о которых вы сообщаете.

Другие вопросы по тегам