Skip to content

Commit

Permalink
Generate minimal headers on 304 Not Modified
Browse files Browse the repository at this point in the history
Favour 'ETag' over 'Last-Modified' when they are both enabled. It's
redundant to produce both, especially since 'ETag' is a much stronger
validator.

Avoid producing 'ETag', 'Last-Modified' or 'Cache-Control' or any
content-related headers when raising a '304 Not Modified' in static
resources.

Set the encoding to 'Soup.Encoding.NONE' to produce response headers
consistent with no content.
  • Loading branch information
arteymix committed Dec 18, 2015
1 parent fe10d3d commit d876382
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 21 deletions.
3 changes: 3 additions & 0 deletions src/valum-router.vala
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,9 @@ namespace Valum {
} catch (Success.PARTIAL_CONTENT s) {
res.status = s.code;
res.headers.append ("Range", s.message);
} catch (Redirection.NOT_MODIFIED r) {
res.status = r.code;
res.headers.set_encoding (global::Soup.Encoding.NONE);
} catch (Redirection r) {
res.status = r.code;
res.headers.append ("Location", r.message);
Expand Down
37 changes: 16 additions & 21 deletions src/valum-static.vala
Original file line number Diff line number Diff line change
Expand Up @@ -90,37 +90,32 @@ namespace Valum.Static {
return (req, res, next, stack) => {
var file = root.resolve_relative_path (stack.pop_tail ().get_string ());

if (ServeFlags.PUBLIC in serve_flags)
res.headers.append ("Cache-Control", "public");

try {
var cached = false;

if (ServeFlags.ETAG in serve_flags) {
var etag = "\"%s\"".printf (file.query_info (FileAttribute.ETAG_VALUE,
FileQueryInfoFlags.NONE).get_etag ());

res.headers.replace ("ETag", etag);
if (etag == req.headers.get_one ("If-None-Match"))
throw new Redirection.NOT_MODIFIED ("");

cached |= (etag == req.headers.get_one ("If-None-Match"));
res.headers.replace ("ETag", etag);
}

if (ServeFlags.LAST_MODIFIED in serve_flags) {
else if (ServeFlags.LAST_MODIFIED in serve_flags) {
var last_modified = file.query_info (FileAttribute.TIME_MODIFIED,
FileQueryInfoFlags.NONE).get_modification_time ();

res.headers.replace ("Last-Modified",
new Soup.Date.from_time_t (last_modified.tv_sec).to_string (Soup.DateFormat.HTTP));

var if_modified_since = req.headers.get_one ("If-Modified-Since");

cached |=
if_modified_since != null &&
new Soup.Date.from_string (if_modified_since).to_timeval ().tv_sec >= last_modified.tv_sec;
if (if_modified_since != null && new Soup.Date.from_string (if_modified_since).to_timeval ().tv_sec >= last_modified.tv_sec)
throw new Redirection.NOT_MODIFIED ("");

res.headers.replace ("Last-Modified",
new Soup.Date.from_time_t (last_modified.tv_sec).to_string (Soup.DateFormat.HTTP));
}

if (cached)
throw new Redirection.NOT_MODIFIED ("");
if (ServeFlags.PUBLIC in serve_flags)
res.headers.append ("Cache-Control", "public");

var file_read_stream = file.read ();

Expand Down Expand Up @@ -200,22 +195,22 @@ namespace Valum.Static {
return;
}

if (ServeFlags.PUBLIC in serve_flags)
res.headers.append ("Cache-Control", "public");

if (ServeFlags.ETAG in serve_flags) {
var etag = path in etag_cache ?
etag_cache[path] :
"\"%s\"".printf (Checksum.compute_for_bytes (ChecksumType.SHA1, lookup));

etag_cache[path] = etag;

res.headers.replace ("ETag", etag);

if (etag == req.headers.get_one ("If-None-Match"))
throw new Redirection.NOT_MODIFIED ("");

res.headers.replace ("ETag", etag);
}

if (ServeFlags.PUBLIC in serve_flags)
res.headers.append ("Cache-Control", "public");

// set the content-type based on a good guess
bool uncertain;
res.headers.set_content_type (ContentType.guess (path, lookup.get_data (), out uncertain), null);
Expand Down

0 comments on commit d876382

Please sign in to comment.