Http Proxy сервлет с возможностями кеширования - PullRequest
0 голосов
/ 14 мая 2019

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

Конечно, проблема в том, что я не могу кэшировать весь ответ, так как, если я передам его через конвейер, входной поток будет использован итогда кэшированный файл больше недоступен.

Как вы думаете, как лучше всего подойти к этому?Как я могу скопировать HTTPResponse (или только HTTPEntity), не потребляя его содержимое?

1 Ответ

1 голос
/ 14 мая 2019

InputStream, если не указано иное, является одиночным выстрелом: вы потребляете его один раз и все.

Если вы хотите прочитать его много раз, это уже не просто поток, этопоток с буфером.Для кэширования входного потока вы должны записать содержимое ответа в файл или в память, чтобы вы могли перечитать его снова (несколько раз).

HTTPEntity можно перечитать, но это зависитна тип реализации.Вы можете проверить это с помощью .isRepeatable(), например.Это оригинальный Javadoc Apache.

в потоковом режиме : контент получен из потока или сгенерирован на лету.В частности, в эту категорию входят объекты, получаемые из соединения.Потоковые объекты, как правило, не повторяются.
автономные : содержимое находится в памяти или получено с помощью средств, которые не зависят от соединения или другого объекта.Автономные сущности обычно повторяемы.
упаковка : содержимое получено от другой сущности.

Вы можете использовать FileEntity, который self-содержится и, следовательно, повторяется (перечитывается).

Чтобы заархивировать это (кэшировать в файл), вы можете прочитать содержимое HTTPEntity и записать его в File.После этого вы можете создать FileEntity с помощью File, который мы создали и написали ранее.Наконец, вам просто нужно заменить сущность HTTPResponse новой FileEntity.

Вот простой пример без контекста:

// Get the untouched entity from the HTTPResponse
HttpEntity originalEntity = response.getEntity();

// Obtain the content type of the response.
String contentType = originalEntity.getContentType().getElements()[0].getValue();

// Create a file for the cache. You should hash the the URL and pass it as the filename.
File targetFile = new File("/some/cache/folder/{--- HERE the URL in HASHED form ---}");

// Copy the input stream into the file above.
FileUtils.copyInputStreamToFile(originalEntity.getContent(), targetFile);

// Create a new Entity, pass the file and the replace the HTTPResponse's entity with it.
HttpEntity newEntity = new FileEntity(targetFile, ContentType.getByMimeType(contentType));
response.setEntity(newEntity);

Теперь вы можете перечитывать содержимое файла снова и снова в будущем.
Вам просто нужно найтифайл на основе URI:)

Для кэширования в памяти вы можете использовать ByteArrayEntity.

Этот метод просто кэширует тело. Не заголовки http.

Обновление: альтернатива

Или вы можете использовать Apache HttpClient Cache .
https://hc.apache.org/httpcomponents-client-ga/tutorial/html/caching.html

...