* libs/http: fix header handling in conditionals.lua
[project/luci.git] / libs / httpd / luasrc / httpd / handler / file.lua
1 --[[
2
3 HTTP server implementation for LuCI - luci handler
4 (c) 2008 Steven Barth <steven@midlink.org>
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.httpd.handler.file", package.seeall)
17
18 require("luci.httpd.module")
19 require("luci.http.protocol.date")
20 require("luci.http.protocol.mime")
21 require("luci.http.protocol.conditionals")
22 require("luci.fs")
23 require("ltn12")
24
25 Simple = luci.util.class(luci.httpd.module.Handler)
26 Response = luci.httpd.module.Response
27
28 function Simple.__init__(self, docroot, dirlist)
29         luci.httpd.module.Handler.__init__(self)
30         self.docroot = docroot
31         self.dirlist = dirlist and true or false
32         self.mime    = luci.http.protocol.mime
33         self.date    = luci.http.protocol.date
34         self.cond    = luci.http.protocol.conditionals
35 end
36
37 function Simple.getfile(self, uri)
38         local file = self.docroot .. uri:gsub("%.%./+", "")
39         local stat = luci.fs.stat(file)
40
41         return file, stat
42 end
43
44 function Simple.handle_get(self, request, sourcein, sinkerr)
45         local file, stat = self:getfile(request.env.PATH_INFO)
46
47         if stat then
48                 if stat.type == "regular" then
49
50                         -- Generate Entity Tag
51                         local etag = self.cond.mk_etag( stat )
52
53                         -- Check conditionals
54                         local ok, code, hdrs
55
56                         ok, code, hdrs = self.cond.if_modified_since( request, stat )
57                         if ok then
58                                 ok, code, hdrs = self.cond.if_match( request, stat )
59                                 if ok then
60                                         ok, code, hdrs = self.cond.if_unmodified_since( request, stat )
61                                         if ok then
62                                                 ok, code, hdrs = self.cond.if_none_match( request, stat )
63                                                 if ok then
64                                                         -- Send Response
65                                                         return Response(
66                                                                 200, {
67                                                                         ["Date"]           = self.date.to_http( os.time() );
68                                                                         ["Last-Modified"]  = self.date.to_http( stat.mtime );
69                                                                         ["Content-Type"]   = self.mime.to_mime( file );
70                                                                         ["Content-Length"] = stat.size;
71                                                                         ["ETag"]           = etag;
72                                                                 }
73                                                         ), ltn12.source.file(io.open(file))
74                                                 else
75                                                         return Response( code, hdrs or { } ),
76                                                                 ltn12.source.empty()
77                                                 end
78                                         else
79                                                 return Response( code, hdrs or { } ),
80                                                         ltn12.source.empty()
81                                         end
82                                 else
83                                         return Response( code, hdrs or { } ),
84                                                 ltn12.source.empty()
85                                 end
86                         else
87                                 return Response( code, hdrs or { } ),
88                                         ltn12.source.empty()
89                         end
90                 else
91                         return self:failure(403, "Unable to transmit " .. stat.type .. " " .. file)
92                 end
93         else
94                 return self:failure(404, "No such file: " .. file)
95         end
96 end
97
98 function Simple.handle_head(self, ...)
99         local response, sourceout = self:handle_get(...)
100         return response
101 end