Как я могу сгенерировать измененные http-заголовки с помощью Compojure?

#http #clojure #http-headers #compojure

#http #clojure #http-заголовки #compojure

Вопрос:

Я пытаюсь повысить производительность для клиентов, извлекающих страницы с моего веб-сервера Compojure. Мы обрабатываем кучу статических файлов (JS, CSS) с помощью (compojure.route/resources "/") , которая ищет файлы в файловой системе, преобразует их в URL-адреса, а затем отправляет их в виде потоков. При преобразовании в streams, похоже, теряются все метаданные файла, такие как время изменения.

Я могу обернуть обработчик статических ресурсов и добавить заголовок Expires or Cache-Control: max-age , но это не позволяет клиенту отправлять какие-либо запросы вообще. Полезно, но эти файлы иногда меняются (когда мы выпускаем релиз).

В идеале я хотел бы, чтобы клиент доверял своей собственной кэшированной версии, скажем, в течение часа, и отправлял запрос с If-Modified-Since заголовком по истечении этого часа. Тогда мы можем просто вернуться 304 Not Modified , и клиент избегает загрузки пары сотен килограммов javascript.

Похоже, что я могу установить Last-Modified заголовок при отправке ответа, и это заставляет клиента квалифицировать последующие запросы с помощью If-Modified-Since заголовков. Отлично, за исключением того, что мне пришлось бы переписать большую часть кода в compojure.route/resources , чтобы добавить Last-Modified — не сложно, но утомительно — и придумать еще какой-нибудь код для распознавания If-Modified-Since заголовка и реагирования на него. Не монументальная задача, но и не простая.

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

Ответ №1:

Черт возьми, я заставил это работать, используя промежуточное программное обеспечение Ring wrap-file-info от Ring; Мне немного неловко, что я искал это в Compojure вместо Ring. Однако compojure.route обработчики files и resources оба обслуживают потоки вместо файлов или URL-адресов, и, конечно, Ring не может определить метаданные из этого.

Мне пришлось написать в основном копию, resources которая вместо этого возвращает File ; когда она была завернута в wrap-file-info , это соответствовало моим потребностям. Тем не менее, я не возражал бы против немного лучшего решения, которое не требует копирования фрагмента кода из Compojure.

Ответ №2:

Рассматривали ли вы возможность использования ring-etag-middleware? Для генерации тега entity используется дата последнего изменения файла. Затем он вводит 304 при совпадении с заголовком if-none-match в запросе.