2016-11-09 14 views
1

Я добавил пользовательское поведение кэширования в свое приложение, похожее на то, что Тьерри предложил in this article. Для каждого CSS, JS и HTML файл-сервер в моем статического контента я добавляю две следующие заголовки:Должен ли я вручную возвращать 304 ответ для кэшированных запросов (ETag) в Restlet?

// Added by me 
ETag: "0c635aa7113262fac7606da2432e00f5" // md5(last_mod_date_of_file) 
Cache-Control: max-age=31536000 // one year 

// Automatically added by Restlet (probably Directory class?) 
Date: Wed, 09 Nov 2016 11:50:53 GMT 
Expires: Wed, 09 Nov 2016 12:00:53 GMT 
Last-Modified: Wed, 09 Nov 2016 17:30:56 GMT 

Это прекрасно работает, однако я заметил, что после развертывания кода на тестовом сервере и нажав F5 в Chrome, Я снова получаю весь ответ (с возвратом HTTP 200).

Я заметил, что эти запросы используют правильные заголовки тоже:

Cache-Control:max-age=0 
If-Modified-Since: Wed, 09 Nov 2016 17:30:56 GMT 
If-None-Match: "0c635aa7113262fac7606da2432e00f5" 

Мой вопрос, я должен делать никаких ручных проверок If-None-Match заголовка в моем сервере фильтра и вернуть 304 ответ, затем? Или это обрабатывается Restlet?

Примечание: в этой проблеме немного странно, так это то, что она, похоже, работает должным образом в моей локальной среде разработки. Я также немного смущен относительно того, почему Expires задано Restlet до даты доLast-Modified. Я попытаюсь отладить, если это корень зла, но это не отменяет мой вопрос о ручной настройке статуса 304 и проверяет ETags на сервере.

+0

Обычно сценарий состоит в том, чтобы иметь обратный прокси-сервер кэширования между браузером и вашим Java-приложением. В этом случае 304 обрабатывается им, и вам не нужно беспокоиться внутри приложения. Будьте осторожны, потому что пограничный сервер может интерпретировать заголовки не так, как определяет браузер или стандарт HTTP. Например. NGINX настроен очень сильно (пропущен). – cruftex

+1

Из заголовка выше, Last-Expires - через 10 минут после текущего времени. На самом деле последнее изменение временного шва ошибочно. Может быть, разное время или зоны на строительстве и производстве? – cruftex

ответ

2

Хорошо, так что я смог понять это, и я отправляю ответы ниже.

Должен ли я выполнять ручную проверку заголовка If-None-Match в моем сервере и возвращать ответ 304?

Нет, вам не обязательно делать это самостоятельно. Это автоматически обрабатывается Restlet (DirectoryServerResource позаботится об этом).

В чем была проблема?

Проблема была в том, что заголовок Last-Modified был установлен в будущую дату. Это произошло потому, что мой производственный сервер находился в UTC-8 часовом поясе, тогда как я развиваюсь в UTC+1.

Как я исправился?

Необходимо было познакомиться с API-интерфейсом Restlet, но тогда решение было тривиально. Я убедился, что когда мое приложение запущено, оно считывает свойство моего каталога приложений из операционной системы File Last Modified, так как это значение, которое я хотел использовать в заголовке Last-Modified. Теперь вы не можете просто установить этот заголовок на response в Filter, поскольку автоматическая обработка заголовков кеширования HTTP происходит до этого в упомянутом DirectoryServerResource классе. Таким образом, решение заключается в следующем:

Создать класс, который расширяет DSR (что дает вам все автоматическая обработка бесплатно кэширование) и изменить свой метод handle() так что Last-Modified заголовка устанавливается перед этими логическими пинками в:

public class WebAssetsResource extends DirectoryServerResource { 
    @Override 
    public Representation handle() { 
     Date desiredDate = ...; // I read this from File System 
     getInfo().setModificationDate(desiredDate); 
     return super.handle(); // Automatic logic will use desired date 
    } 
} 

Теперь убедитесь, что ваш вновь созданный ресурс используется пользовательским классом Directory.

public class CachedWebAssetsDirectory extends Directory { 
    public CachedWebAssetsDirectory(Context context, Reference rootLocalReference) { 
     super(context, rootLocalReference); 
     setTargetClass(WebAssetsResource.class); // Needed so that Restlet will use our implementation of a ServerResource to serve static files 
    } 
} 

После этого вы можете использовать CachedWebAssetsDirectory, как вы хотите, строить любые пользовательские фильтры поверх этого.