#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 в запросе.