Политика 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";
Я заметил следующее:
- Отключить кеши
- Все отлично работает, оба изображения загружаются
Затем попробуйте с включенными кешами:
- Включить кеши
- Загрузка изображения 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
Значение заголовка затем кэшируется для последующих запросов, вызывая проблемы, аналогичные тем, о которых вы сообщаете.