mirror of https://github.com/kiwix/libkiwix.git
ETags for ZIM content use the ZIM file UUID
This commit is contained in:
parent
a31ccb6588
commit
b249edee60
|
@ -511,8 +511,10 @@ MHD_Result InternalServer::handlerCallback(struct MHD_Connection* connection,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response->getReturnCode() == MHD_HTTP_OK && !etag_not_needed(request))
|
if (response->getReturnCode() == MHD_HTTP_OK
|
||||||
response->set_server_id(m_server_id);
|
&& response->get_kind() == Response::DYNAMIC_CONTENT
|
||||||
|
&& !etag_not_needed(request))
|
||||||
|
response->set_etag_body(m_server_id);
|
||||||
|
|
||||||
auto ret = response->send(request, connection);
|
auto ret = response->send(request, connection);
|
||||||
auto end_time = std::chrono::steady_clock::now();
|
auto end_time = std::chrono::steady_clock::now();
|
||||||
|
@ -542,7 +544,7 @@ std::unique_ptr<Response> InternalServer::handle_request(const RequestContext& r
|
||||||
+ urlNotFoundMsg;
|
+ urlNotFoundMsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ETag etag = get_matching_if_none_match_etag(request);
|
const ETag etag = get_matching_if_none_match_etag(request, m_server_id);
|
||||||
if ( etag )
|
if ( etag )
|
||||||
return Response::build_304(*this, etag);
|
return Response::build_304(*this, etag);
|
||||||
|
|
||||||
|
@ -611,11 +613,11 @@ bool InternalServer::etag_not_needed(const RequestContext& request) const
|
||||||
}
|
}
|
||||||
|
|
||||||
ETag
|
ETag
|
||||||
InternalServer::get_matching_if_none_match_etag(const RequestContext& r) const
|
InternalServer::get_matching_if_none_match_etag(const RequestContext& r, const std::string& etagBody) const
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
const std::string etag_list = r.get_header(MHD_HTTP_HEADER_IF_NONE_MATCH);
|
const std::string etag_list = r.get_header(MHD_HTTP_HEADER_IF_NONE_MATCH);
|
||||||
return ETag::match(etag_list, m_server_id);
|
return ETag::match(etag_list, etagBody);
|
||||||
} catch (const std::out_of_range&) {
|
} catch (const std::out_of_range&) {
|
||||||
return ETag();
|
return ETag();
|
||||||
}
|
}
|
||||||
|
@ -1049,6 +1051,11 @@ std::unique_ptr<Response> InternalServer::handle_content(const RequestContext& r
|
||||||
+ suggestSearchMsg(searchURL, kiwix::urlDecode(pattern));
|
+ suggestSearchMsg(searchURL, kiwix::urlDecode(pattern));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string archiveUuid(archive->getUuid());
|
||||||
|
const ETag etag = get_matching_if_none_match_etag(request, archiveUuid);
|
||||||
|
if ( etag )
|
||||||
|
return Response::build_304(*this, etag);
|
||||||
|
|
||||||
auto urlStr = url.substr(prefixLength + bookName.size());
|
auto urlStr = url.substr(prefixLength + bookName.size());
|
||||||
if (urlStr[0] == '/') {
|
if (urlStr[0] == '/') {
|
||||||
urlStr = urlStr.substr(1);
|
urlStr = urlStr.substr(1);
|
||||||
|
@ -1067,6 +1074,7 @@ std::unique_ptr<Response> InternalServer::handle_content(const RequestContext& r
|
||||||
return build_redirect(bookName, getFinalItem(*archive, entry));
|
return build_redirect(bookName, getFinalItem(*archive, entry));
|
||||||
}
|
}
|
||||||
auto response = ItemResponse::build(*this, request, entry.getItem());
|
auto response = ItemResponse::build(*this, request, entry.getItem());
|
||||||
|
response->set_etag_body(archiveUuid);
|
||||||
|
|
||||||
if (m_verbose.load()) {
|
if (m_verbose.load()) {
|
||||||
printf("Found %s\n", entry.getPath().c_str());
|
printf("Found %s\n", entry.getPath().c_str());
|
||||||
|
@ -1120,6 +1128,11 @@ std::unique_ptr<Response> InternalServer::handle_raw(const RequestContext& reque
|
||||||
+ noSuchBookErrorMsg(bookName);
|
+ noSuchBookErrorMsg(bookName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string archiveUuid(archive->getUuid());
|
||||||
|
const ETag etag = get_matching_if_none_match_etag(request, archiveUuid);
|
||||||
|
if ( etag )
|
||||||
|
return Response::build_304(*this, etag);
|
||||||
|
|
||||||
// Remove the beggining of the path:
|
// Remove the beggining of the path:
|
||||||
// /raw/<bookName>/<kind>/foo
|
// /raw/<bookName>/<kind>/foo
|
||||||
// ^^^^^ ^ ^
|
// ^^^^^ ^ ^
|
||||||
|
@ -1129,13 +1142,17 @@ std::unique_ptr<Response> InternalServer::handle_raw(const RequestContext& reque
|
||||||
try {
|
try {
|
||||||
if (kind == "meta") {
|
if (kind == "meta") {
|
||||||
auto item = archive->getMetadataItem(itemPath);
|
auto item = archive->getMetadataItem(itemPath);
|
||||||
return ItemResponse::build(*this, request, item);
|
auto response = ItemResponse::build(*this, request, item);
|
||||||
|
response->set_etag_body(archiveUuid);
|
||||||
|
return response;
|
||||||
} else {
|
} else {
|
||||||
auto entry = archive->getEntryByPath(itemPath);
|
auto entry = archive->getEntryByPath(itemPath);
|
||||||
if (entry.isRedirect()) {
|
if (entry.isRedirect()) {
|
||||||
return build_redirect(bookName, entry.getItem(true));
|
return build_redirect(bookName, entry.getItem(true));
|
||||||
}
|
}
|
||||||
return ItemResponse::build(*this, request, entry.getItem());
|
auto response = ItemResponse::build(*this, request, entry.getItem());
|
||||||
|
response->set_etag_body(archiveUuid);
|
||||||
|
return response;
|
||||||
}
|
}
|
||||||
} catch (zim::EntryNotFound& e ) {
|
} catch (zim::EntryNotFound& e ) {
|
||||||
if (m_verbose.load()) {
|
if (m_verbose.load()) {
|
||||||
|
|
|
@ -148,7 +148,7 @@ class InternalServer {
|
||||||
MustacheData get_default_data() const;
|
MustacheData get_default_data() const;
|
||||||
|
|
||||||
bool etag_not_needed(const RequestContext& r) const;
|
bool etag_not_needed(const RequestContext& r) const;
|
||||||
ETag get_matching_if_none_match_etag(const RequestContext& request) const;
|
ETag get_matching_if_none_match_etag(const RequestContext& request, const std::string& etagBody) const;
|
||||||
std::pair<std::string, Library::BookIdSet> selectBooks(const RequestContext& r) const;
|
std::pair<std::string, Library::BookIdSet> selectBooks(const RequestContext& r) const;
|
||||||
SearchInfo getSearchInfo(const RequestContext& r) const;
|
SearchInfo getSearchInfo(const RequestContext& r) const;
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,8 @@ class Response {
|
||||||
|
|
||||||
void set_code(int code) { m_returnCode = code; }
|
void set_code(int code) { m_returnCode = code; }
|
||||||
void set_kind(Kind k);
|
void set_kind(Kind k);
|
||||||
void set_server_id(const std::string& id) { m_etag.set_body(id); }
|
Kind get_kind() const { return m_kind; }
|
||||||
|
void set_etag_body(const std::string& id) { m_etag.set_body(id); }
|
||||||
void add_header(const std::string& name, const std::string& value) { m_customHeaders[name] = value; }
|
void add_header(const std::string& name, const std::string& value) { m_customHeaders[name] = value; }
|
||||||
|
|
||||||
int getReturnCode() const { return m_returnCode; }
|
int getReturnCode() const { return m_returnCode; }
|
||||||
|
|
|
@ -1136,17 +1136,28 @@ TEST_F(ServerTest, ETagIsTheSameAcrossHeadAndGet)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ServerTest, DifferentServerInstancesProduceDifferentETags)
|
TEST_F(ServerTest, DifferentServerInstancesProduceDifferentETagsForDynamicContent)
|
||||||
{
|
{
|
||||||
ZimFileServer zfs2(SERVER_PORT + 1, ZimFileServer::DEFAULT_OPTIONS, ZIMFILES);
|
ZimFileServer zfs2(SERVER_PORT + 1, ZimFileServer::DEFAULT_OPTIONS, ZIMFILES);
|
||||||
for ( const Resource& res : all200Resources() ) {
|
for ( const Resource& res : all200Resources() ) {
|
||||||
if ( !res.etag_expected() ) continue;
|
if ( res.kind != DYNAMIC_CONTENT ) continue;
|
||||||
const auto h1 = zfs1_->HEAD(res.url);
|
const auto h1 = zfs1_->HEAD(res.url);
|
||||||
const auto h2 = zfs2.HEAD(res.url);
|
const auto h2 = zfs2.HEAD(res.url);
|
||||||
EXPECT_NE(h1->get_header_value("ETag"), h2->get_header_value("ETag"));
|
EXPECT_NE(h1->get_header_value("ETag"), h2->get_header_value("ETag"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ServerTest, DifferentServerInstancesProduceIdenticalETagsForZimContent)
|
||||||
|
{
|
||||||
|
ZimFileServer zfs2(SERVER_PORT + 1, ZimFileServer::DEFAULT_OPTIONS, ZIMFILES);
|
||||||
|
for ( const Resource& res : all200Resources() ) {
|
||||||
|
if ( res.kind != ZIM_CONTENT ) continue;
|
||||||
|
const auto h1 = zfs1_->HEAD(res.url);
|
||||||
|
const auto h2 = zfs2.HEAD(res.url);
|
||||||
|
EXPECT_EQ(h1->get_header_value("ETag"), h2->get_header_value("ETag"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(ServerTest, CompressionInfluencesETag)
|
TEST_F(ServerTest, CompressionInfluencesETag)
|
||||||
{
|
{
|
||||||
for ( const Resource& res : resources200Compressible ) {
|
for ( const Resource& res : resources200Compressible ) {
|
||||||
|
|
Loading…
Reference in New Issue