1 -- Copyright 2008 Freifunk Leipzig / Jo-Philipp Wich <jow@openwrt.org>
2 -- Licensed to the public under the Apache License 2.0.
4 -- This class provides basic ETag handling and implements most of the
5 -- conditional HTTP/1.1 headers specified in RFC2616 Sct. 14.24 - 14.28 .
6 module("luci.http.protocol.conditionals", package.seeall)
8 local date = require("luci.http.protocol.date")
11 function mk_etag( stat )
13 return string.format( '"%x-%x-%x"', stat.ino, stat.size, stat.mtime )
17 -- Test whether the given message object contains an "If-Match" header and
18 -- compare it against the given stat object.
19 function if_match( req, stat )
21 local etag = mk_etag( stat )
23 -- Check for matching resource
24 if type(h['If-Match']) == "string" then
25 for ent in h['If-Match']:gmatch("([^, ]+)") do
26 if ( ent == '*' or ent == etag ) and stat ~= nil then
37 -- Test whether the given message object contains an "If-Modified-Since" header
38 -- and compare it against the given stat object.
39 function if_modified_since( req, stat )
43 if type(h['If-Modified-Since']) == "string" then
44 local since = date.to_unix( h['If-Modified-Since'] )
46 if stat == nil or since < stat.mtime then
51 ["ETag"] = mk_etag( stat );
52 ["Date"] = date.to_http( os.time() );
53 ["Last-Modified"] = date.to_http( stat.mtime )
60 -- Test whether the given message object contains an "If-None-Match" header and
61 -- compare it against the given stat object.
62 function if_none_match( req, stat )
64 local etag = mk_etag( stat )
65 local method = req.env and req.env.REQUEST_METHOD or "GET"
67 -- Check for matching resource
68 if type(h['If-None-Match']) == "string" then
69 for ent in h['If-None-Match']:gmatch("([^, ]+)") do
70 if ( ent == '*' or ent == etag ) and stat ~= nil then
71 if method == "GET" or method == "HEAD" then
74 ["Date"] = date.to_http( os.time() );
75 ["Last-Modified"] = date.to_http( stat.mtime )
87 -- The If-Range header is currently not implemented due to the lack of general
88 -- byte range stuff in luci.http.protocol . This function will always return
89 -- false, 412 to indicate a failed precondition.
90 function if_range( req, stat )
91 -- Sorry, no subranges (yet)
95 -- Test whether the given message object contains an "If-Unmodified-Since"
96 -- header and compare it against the given stat object.
97 function if_unmodified_since( req, stat )
101 if type(h['If-Unmodified-Since']) == "string" then
102 local since = date.to_unix( h['If-Unmodified-Since'] )
104 if stat ~= nil and since <= stat.mtime then