Setting Cache-Control: for three types of content

At this point the ETag value for ZIM content is still generated from the
timestamp of the server start-up time.
This commit is contained in:
Veloman Yunkan 2022-10-09 16:28:58 +04:00
parent 5471819021
commit 190156e095
6 changed files with 39 additions and 15 deletions

View File

@ -37,7 +37,7 @@ namespace {
// into the ETag for ETag::Option opt.
// IMPORTANT: The characters in all_options must come in sorted order (so that
// IMPORTANT: isValidOptionsString() works correctly).
const char all_options[] = "cz";
const char all_options[] = "Zz";
static_assert(ETag::OPTION_COUNT == sizeof(all_options) - 1, "");

View File

@ -51,7 +51,7 @@ class ETag
{
public: // types
enum Option {
CACHEABLE_ENTITY,
ZIM_CONTENT,
COMPRESSED_CONTENT,
OPTION_COUNT
};

View File

@ -606,11 +606,8 @@ MustacheData InternalServer::get_default_data() const
bool InternalServer::etag_not_needed(const RequestContext& request) const
{
const std::string url = request.get_url();
return kiwix::startsWith(url, "/catalog")
|| url == "/search"
|| url == "/suggest"
|| url == "/random"
|| url == "/catch/external";
return kiwix::startsWith(url, "/skin")
|| url == "/random";
}
ETag
@ -761,7 +758,7 @@ std::unique_ptr<Response> InternalServer::handle_skin(const RequestContext& requ
*this,
getResource(resourceName),
getMimeTypeForFile(resourceName));
response->set_cacheable();
response->set_kind(Response::STATIC_RESOURCE);
return std::move(response);
} catch (const ResourceNotFound& e) {
return HTTP404Response(*this, request)

View File

@ -102,6 +102,14 @@ bool compress(std::string &content) {
}
const char* getCacheControlHeader(Response::Kind k)
{
switch(k) {
case Response::STATIC_RESOURCE: return "max-age=31536000, immutable";
case Response::ZIM_CONTENT: return "max-age=3600, must-revalidate";
default: return "max-age=0, must-revalidate";
}
}
} // unnamed namespace
@ -112,6 +120,13 @@ Response::Response(bool verbose)
add_header(MHD_HTTP_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN, "*");
}
void Response::set_kind(Kind k)
{
m_kind = k;
if ( k == ZIM_CONTENT )
m_etag.set_option(ETag::ZIM_CONTENT);
}
std::unique_ptr<Response> Response::build(const InternalServer& server)
{
return std::unique_ptr<Response>(new Response(server.m_verbose.load()));
@ -122,6 +137,9 @@ std::unique_ptr<Response> Response::build_304(const InternalServer& server, cons
auto response = Response::build(server);
response->set_code(MHD_HTTP_NOT_MODIFIED);
response->m_etag = etag;
if ( etag.get_option(ETag::ZIM_CONTENT) ) {
response->set_kind(Response::ZIM_CONTENT);
}
if ( etag.get_option(ETag::COMPRESSED_CONTENT) ) {
response->add_header(MHD_HTTP_HEADER_VARY, "Accept-Encoding");
}
@ -355,7 +373,7 @@ MHD_Result Response::send(const RequestContext& request, MHD_Connection* connect
MHD_Response* response = create_mhd_response(request);
MHD_add_response_header(response, MHD_HTTP_HEADER_CACHE_CONTROL,
m_etag.get_option(ETag::CACHEABLE_ENTITY) ? "max-age=2723040, public" : "no-cache, no-store, must-revalidate");
getCacheControlHeader(m_kind));
const std::string etag = m_etag.get_etag();
if ( ! etag.empty() )
MHD_add_response_header(response, MHD_HTTP_HEADER_ETAG, etag.c_str());
@ -411,7 +429,7 @@ ItemResponse::ItemResponse(bool verbose, const zim::Item& item, const std::strin
m_mimeType(mimetype)
{
m_byteRange = byterange;
set_cacheable();
set_kind(Response::ZIM_CONTENT);
add_header(MHD_HTTP_HEADER_CONTENT_TYPE, m_mimeType);
}
@ -423,14 +441,14 @@ std::unique_ptr<Response> ItemResponse::build(const InternalServer& server, cons
if (noRange && is_compressible_mime_type(mimetype)) {
// Return a contentResponse
auto response = ContentResponse::build(server, item.getData(), mimetype);
response->set_cacheable();
response->set_kind(Response::ZIM_CONTENT);
response->m_byteRange = byteRange;
return std::move(response);
}
if (byteRange.kind() == ByteRange::RESOLVED_UNSATISFIABLE) {
auto response = Response::build_416(server, item.getSize());
response->set_cacheable();
response->set_kind(Response::ZIM_CONTENT);
return response;
}

View File

@ -45,6 +45,14 @@ class InternalServer;
class RequestContext;
class Response {
public:
enum Kind
{
STATIC_RESOURCE,
ZIM_CONTENT,
DYNAMIC_CONTENT
};
public:
Response(bool verbose);
virtual ~Response() = default;
@ -57,7 +65,7 @@ class Response {
MHD_Result send(const RequestContext& request, MHD_Connection* connection);
void set_code(int code) { m_returnCode = code; }
void set_cacheable() { m_etag.set_option(ETag::CACHEABLE_ENTITY); }
void set_kind(Kind k);
void set_server_id(const std::string& id) { m_etag.set_server_id(id); }
void add_header(const std::string& name, const std::string& value) { m_customHeaders[name] = value; }
@ -68,6 +76,7 @@ class Response {
MHD_Response* create_error_response(const RequestContext& request) const;
protected: // data
Kind m_kind = DYNAMIC_CONTENT;
bool m_verbose;
int m_returnCode;
ByteRange m_byteRange;

View File

@ -35,7 +35,7 @@ struct Resource
ResourceKind kind;
const char* url;
bool etag_expected() const { return kind != DYNAMIC_CONTENT; }
bool etag_expected() const { return kind != STATIC_CONTENT; }
};
std::ostream& operator<<(std::ostream& out, const Resource& r)
@ -47,7 +47,7 @@ std::ostream& operator<<(std::ostream& out, const Resource& r)
typedef std::vector<Resource> ResourceCollection;
const ResourceCollection resources200Compressible{
{ STATIC_CONTENT, "/ROOT/" },
{ DYNAMIC_CONTENT, "/ROOT/" },
{ STATIC_CONTENT, "/ROOT/skin/autoComplete.min.js" },
{ STATIC_CONTENT, "/ROOT/skin/css/autoComplete.css" },