* libs/http: add Date header for 304 responses
[project/luci.git] / libs / http / luasrc / http / protocol / conditionals.lua
1 --[[
2
3 HTTP protocol implementation for LuCI - RFC2616 / 14.19, 14.24 - 14.28
4 (c) 2008 Freifunk Leipzig / Jo-Philipp Wich <xm@leipzig.freifunk.net>
5
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
9
10 http://www.apache.org/licenses/LICENSE-2.0
11
12 $Id$
13
14 ]]--
15
16 module("luci.http.protocol.conditionals", package.seeall)
17
18 local date = require("luci.http.protocol.date")
19
20
21 -- 14.19 / ETag
22 function mk_etag( stat )
23 if stat ~= nil then
24 return string.format( '"%x-%x-%x"', stat.ino, stat.size, stat.mtime )
25 end
26 end
27
28 -- 14.24 / If-Match
29 function if_match( req, stat )
30 local h = req.headers
31 local etag = mk_etag( stat )
32
33 -- Check for matching resource
34 if type(h['If-Match']) == "string" then
35 for ent in h['If-Match']:gmatch("([^, ]+)") do
36 if ( ent == '*' or ent == etag ) and stat ~= nil then
37 return true
38 end
39 end
40
41 return false, 412
42 end
43
44 return true
45 end
46
47 -- 14.25 / If-Modified-Since
48 function if_modified_since( req, stat )
49 local h = req.headers
50
51 -- Compare mtimes
52 if type(h['If-Modified-Since']) == "string" then
53 local since = date.to_unix( h['If-Modified-Since'] )
54
55 if stat == nil or since < stat.mtime then
56 return true
57 end
58
59 return false, 304, {
60 ["ETag"] = mk_etag( stat );
61 ["Date"] = date.to_http( os.time() );
62 ["Last-Modified"] = date.to_http( stat.mtime )
63 }
64 end
65
66 return true
67 end
68
69 -- 14.26 / If-None-Match
70 function if_none_match( req, stat )
71 local h = req.headers
72 local etag = mk_etag( stat )
73
74 -- Check for matching resource
75 if type(h['If-None-Match']) == "string" then
76 for ent in h['If-None-Match']:gmatch("([^, ]+)") do
77 if ( ent == '*' or ent == etag ) and stat ~= nil then
78 if req.request_method == "get" or
79 req.request_method == "head"
80 then
81 return false, 304, {
82 ["ETag"] = mk_etag( stat );
83 ["Date"] = date.to_http( os.time() );
84 ["Last-Modified"] = date.to_http( stat.mtime )
85 }
86 else
87 return false, 412
88 end
89 end
90 end
91 end
92
93 return true
94 end
95
96 -- 14.27 / If-Range
97 function if_range( req, stat )
98 -- Sorry, no subranges (yet)
99 return false, 412
100 end
101
102 -- 14.28 / If-Unmodified-Since
103 function if_unmodified_since( req, stat )
104 local h = req.headers
105
106 -- Compare mtimes
107 if type(h['If-Unmodified-Since']) == "string" then
108 local since = date.to_unix( h['If-Unmodified-Since'] )
109
110 if stat ~= nil and since <= stat.mtime then
111 return false, 412
112 end
113 end
114
115 return true
116 end