S3 CORS, всегда отправляйте Vary: Origin
Я использую ведро S3 позади Cloudfront с включенным CORS. Если клиент делает запрос с заголовком Origin, тогда S3 (и облачный фронт) отвечают заголовком "Vary: Origin", однако, если запрос сделан без заголовка Origin, тогда ответ не содержит никакого Vary Header.
Это проблематично, потому что я использую ресурс из cloudfront/s3 в теге img, и в этом случае браузер делает запрос без заголовка Origin, а затем делает запрос ajax для указанного изображения. Затем браузер использует кэшированную версию изображения без заголовка Access-Control-Allow-Origin и поэтому отклоняет запрос.
Есть ли способ заставить S3 всегда возвращать заголовок "Vary: Origin"?
3 ответа
Другим решением будет настройка вашего дистрибутива CloudFront для автоматического превращения запросов не-CORS в запросы CORS. Это возможно путем добавления заголовка CORS к каждому запросу, который CloudFront отправляет на S3, с использованием недавно добавленной функции CloudFront "Заголовки запроса Control Edge-To-Origin".
Смотрите объявление о функции здесь: https://aws.amazon.com/blogs/aws/cloudfront-update-https-tls-v1-1v1-2-to-the-origin-addmodify-headers/
И документация здесь: http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/forward-custom-headers.html.
Я сделал аккаунт только для того, чтобы ответить на ваш вопрос, потому что есть очень мало хороших ответов для такого рода проблем (и несколько связанных).
Проблема, которую вы описываете, возникает по какой-то причине в основном в chrome, FF и IE кажутся достаточно умными, чтобы не разделять кеш между AJAX и обычными вызовами в этих случаях.
Эта проблема
Давайте сначала опишем, почему проблема возникает для будущих читателей:
- Браузер (Chrome) спрашивает сервер с помощью обычного
<img>
или же<script>
тег. Если сервер находится в том же домене, он не включает заголовки CORS. - Сервер (S3) возвращает ресурс. Если в запросе отсутствует заголовок Origin, он не присоединяет заголовки CORS к ответу, поскольку они являются избыточными.
- Браузер (Chrome) снова пытается получить ресурс с помощью AJAX, но на этот раз он не обращается к серверу, а смотрит на кэшированный ресурс.
- Браузер (Chrome) Кэшированная версия не имеет заголовков CORS. Он отбросит запрос как нарушение Access-Control-Allow-Origin или другие связанные проблемы.
Решение
В HTML5 есть атрибут, который называется crossorigin
это может быть добавлено к тегам, чтобы показать, что им нужно отправить информацию о происхождении. Возможные значения crossorigin='anonymous'
а также crossorigin='use-credentials'
они не имеют отношения к заданному вопросу, но, как сказано в документации:
По умолчанию (то есть, когда атрибут не указан), CORS вообще не используется.
https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes
Так что просто создайте свои теги изображений, как это <img src='cloundfront.path' crossorigin='use-credentials'>
Это оно. Это довольно неясно, поэтому я надеюсь, что этот ответ сэкономит некоторое время на исследования для группы людей.
Я наткнулся на простой способ заставить Cloudfront всегда добавлять заголовок «Vary: Origin», хотя и недокументированный, насколько я могу судить: вы можете принудительно указать заголовок «Vary», включив «Origin» в ключ кэша CloudFront.
В дистрибутиве Cloudfront нажмите «Изменить поведение» и найдите заголовок «Ключ кеша и запросы происхождения». Если вы используете «Устаревшие настройки кеша», выберите «Источник» под «Добавить заголовок». Если вы используете более новую политику кеширования, вам нужно нажать «Создать политику» и добавить источник в «Параметры ключа кэша», затем вернуться и использовать только что созданную политику.
Мой вариант использования - треки с видеосубтитрами HMTL5, которые не отправляют Origin, если вы используете
crossorigin="anonymous"
, а если нет Origin, нет и Vary: Origin.