Предотвращение дублирования HTTP-запросов для кешируемых ответов

Возможно ли (без кеша запросов прикладного уровня) предотвратить отправку HTTP-запроса для одного и того же ресурса несколько раз, когда он кэшируется? И если да, то как?

Например. вместо

at time 0: GET /data (request#1)
at time 1: GET /data (request#2)
at time 2: received response#1 for request#1 // headers indicate that the response can be cached
at time 3: received response#2 for request#2 // headers indicate that the response can be cached

 

at time 0: GET /data (request#1)
at time 1: GET /data (will wait for the response of request#1)
at time 2: received response#1 for request#1 // headers indicate that the response can be cached
at time 3: returns response#1 for request#2

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


person Nick Russler    schedule 07.09.2020    source источник
comment
Я думаю, что вы сказали, можете ли вы знать, что HTTP-ответ можно кэшировать, прежде чем отправлять его, нет. И еще, зачем тебе это?   -  person Liam    schedule 07.09.2020
comment
Я спрашиваю, могу ли я указать браузеру, что ответ будет кэшироваться. Или я могу сделать запрос только для того, чтобы браузер знал, что ответ будет кэшироваться. Например. запрос HEAD.   -  person Nick Russler    schedule 07.09.2020
comment
Ваш первоначальный ответ может установить некоторые заголовки кэша. чтобы сообщить браузеру, что он должен использовать этот ответ, а не запрашивать новый каждый раз   -  person Liam    schedule 07.09.2020
comment
Метод HTTP HEAD запрашивает заголовки, которые были бы возвращены, если бы вместо этого был запрошен URL-адрес запроса HEAD с помощью метода HTTP GET. Источник   -  person Nick Russler    schedule 07.09.2020
comment
так что да, тогда метод HTTP HEAD запрашивает заголовки, которые были бы возвращены, если бы URL-адрес запроса HEAD вместо этого был запрошен с помощью HTTP, заголовки управления кешем находятся в голове, поэтому они будут включены. Я предполагаю, что браузеры не склонны делать это, поскольку это неэффективно. Один запрос эффективнее, чем два. Я не возглавлял этот запрос, поэтому я предполагаю (будучи я работаю с HTTP в течение 15 лет), что он редко используется   -  person Liam    schedule 07.09.2020
comment
Поскольку он восходит к HTTP 1.1, я предполагаю, что это было больше важно, когда пропускная способность (модем 56k и т. Д.) Была большей проблемой. В наши дни HTTP-запросы редко бывают достаточно большими, чтобы это стоило того.   -  person Liam    schedule 07.09.2020
comment
Это было просто в качестве примера, потому что трудно спрашивать о вещах, которых вы не знаете. Запрос HEAD, конечно, совсем не поможет, так как он просто опускает тело в ответе и по-прежнему требует выполнения дорогостоящей операции на сервере.   -  person Nick Russler    schedule 07.09.2020
comment
Я до сих пор не знаю, в чем ваш вопрос?   -  person Liam    schedule 07.09.2020
comment
Давайте продолжим обсуждение в чате.   -  person Nick Russler    schedule 07.09.2020


Ответы (2)


Мои вопросы: есть ли механизм, чтобы сигнализировать браузеру, что ответ для URI будет кэшироваться

Да, это то, что делают заголовки Cache-control. .

и любые последующие запросы для этого URI могут возвращать ответ любого запроса в полете.... В идеале это было бы частью спецификации HTTP

Никакой HTTP не сделает этого за вас, вам нужно реализовать кеширование самостоятельно. Это то, что делают браузеры.

Я хотел проверить, есть ли уже что-то готовое из коробки.

Библиотеки Javascript обычно не учитывают кэширование, поскольку запрос AJAX обычно предназначен для данных, а любое кэширование данных обычно происходит на сервере. Я не знаю ни одной библиотеки и, конечно, запрашивать библиотеки Js выходит за рамки SO.

person Liam    schedule 08.09.2020
comment
Когда HTTP-запуск указанного ресурса был инициирован, но еще не завершен во время инициации GET на стороне клиента, приведет ли это к отправке, а также к GET, или браузер будет ждать завершения нажатия? Другим вариантом, но тот же вопрос, будет использование тегов предварительной загрузки. - person Nick Russler; 08.09.2020

В зависимости от браузера второй запрос может быть остановлен и обслуживаться, если он кэшируется, например. в Chromium для запросов без диапазона:

Кэш реализует блокировку одного писателя и нескольких считывателей, так что в любой момент времени выполняется только один сетевой запрос для одного и того же ресурса. https://www.chromium.org/developers/design-documents/network-stack/http-cache

Вот пример, когда три одновременных запроса приводят только к одному вызову сервера:

fetch('/data.json').then(async r => console.log(await r.json()));
fetch('/data.json').then(async r => console.log(await r.json()));;
setTimeout(() => fetch('/data.json').then(async r => console.log(await r.json())), 2000);

три звонка

Последующий запрос имеет переданный 0B и имеет тот же случайный номер, показывая, что был сделан только один вызов сервера.

Это поведение не то же самое, например. Firefox: firefox не избегает повторяющихся запросов

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

Для воспроизведения здесь тестового кода: https://gist.github.com/nickrussler/cd74ac1c07884938b205556030414d34

person Nick Russler    schedule 09.09.2020