0bff274cda5b3f13e2fe03fd8df0d58af64e868e
[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         end
61
62         return true
63 end
64
65 -- 14.26 / If-None-Match
66 function if_none_match( req, stat )
67         local h    = req.headers
68         local etag = mk_etag( stat )
69
70         -- Check for matching resource
71         if type(h['If-None-Match']) == "string" then
72                 for ent in h['If-None-Match']:gmatch("([^, ]+)") do
73                         if ( ent == '*' or ent == etag ) and stat ~= nil then
74                                 if req.request_method == "get"  or
75                                    req.request_method == "head"
76                                 then
77                                         h['ETag']          = mk_etag( stat )
78                                         h['Last-Modified'] = date.to_http( stat.mtime )
79
80                                         return false, 304
81                                 else
82                                         return false, 412
83                                 end
84                         end
85                 end
86         end
87
88         return true
89 end
90
91 -- 14.27 / If-Range
92 function if_range( req, stat )
93         -- Sorry, no subranges (yet)
94         return false, 412
95 end
96
97 -- 14.28 / If-Unmodified-Since
98 function if_unmodified_since( req, stat )
99         local h = req.headers
100
101         -- Compare mtimes
102         if type(h['If-Unmodified-Since']) == "string" then
103                 local since = date.to_unix( h['If-Unmodified-Since'] )
104
105                 if stat ~= nil and since <= stat.mtime then
106                         return false, 412
107                 end
108         end
109
110         return true
111 end