Согласование содержимого HTTP и заголовок Range
Как работает Range
работа с заголовком при согласовании контента? Позвольте мне объяснить, но сначала давайте все согласимся со следующим: HTTP является протоколом без сохранения состояния.
Когда HTTP-сервер может отправить несколько представлений одного ресурса, согласование контента используется для определения того, какое представление отправить: клиент может указать свои предпочтения (т. Е. Английский и GIF-файлы), тогда сервер будет соответствовать или - в сценарии, где это не может - сервер выберет, посредством некоторой эвристической оценки, какое представление отправить клиенту.
Пока все хорошо... но что происходит, когда вы бросаете Range
в смесь?
Представьте себе следующий сценарий:
Джон находится в аэропорту в Париже, и его браузер отправляет HTTP-запрос. По какой-то причине его браузер не указывает никаких предпочтений ни по типу контента, ни по языку, ни по сжатию.
GET /uri HTTP/1.1 Host: example.com
Поскольку пройти через него очень мало, сервер посредством некоторой эвристики решает отправить французское представление URI (IP-адрес распознается как исходящий из Франции.)
200 Okay Accept-Ranges: bytes Content: text/html Content-Language: fr ....data...
В середине передачи Джон останавливает загрузку, чтобы успеть на рейс. Джон возобновляет загрузку, как только он прибывает в Нью-Йорк.
GET /uri HTTP/1.1 Host: example.com Range: 2000-3000
Опять же, имея мало информации о предпочтениях клиента, сервер на этот раз решает отправить английское представление URI (IP-адрес распознается как исходящий из Нью-Йорка.)
К этому моменту файл поврежден, так как часть написана на французском, а другая - на английском.
Гипотеза:
- Возможно, клиент запоминает тип и язык контента из первого ответа, чтобы отправить эту информацию обратно на сервер для второго запроса (в
Accept: text/html Accept-Language: fr
). Тем не менее, поскольку ни в RFC2616, ни в RFC7233 ничего не говорится об этом (даже не рекомендации), я считаю, что HTTP-клиенты с таким поведением встречаются редко... но мне еще предстоит это проверить.
Заметки:
- В приведенном выше сценарии мы могли бы легко сделать так, чтобы клиент отправил предпочтения, а сервер был не в состоянии выполнить... и по-прежнему использовать другую эвристику. Проблема сохраняется.
- В качестве другого примера, эта проблема также может существовать в другом вопросе SO: Пример сеанса запроса диапазона http.
TL;DR
GET /uri HTTP/1.1
Host: example.com
Accept: text/html; q=1.0, text/plain; q=0.8, */*; q=0.1
Accept-Language: en; q=1.0, */*; q=0.1
Range: 100-200
В приведенном выше, диапазон относится к какому представлению запрашиваемого ресурса?!
1 ответ
Краткий ответ: не используйте запрос Range без If-Match: поле заголовка запроса etag.