summaryrefslogtreecommitdiffhomepage
path: root/libs
diff options
context:
space:
mode:
authorJo-Philipp Wich <jow@openwrt.org>2008-06-28 16:12:37 +0000
committerJo-Philipp Wich <jow@openwrt.org>2008-06-28 16:12:37 +0000
commite08b97565f2a2dfeb482be0f061bfefa93d32556 (patch)
treec9de80c79c6de3da952fe9a2ca07559884aa3f67 /libs
parent00aceaf624d8e5da2a8f3df161d52599aae2ac41 (diff)
* libs/http: fix header handling in conditionals.lua
* libs/httpd: add support for RFC2616 / 14.24 - 14.28 in file handler, add Date and Expires headers to luci handler
Diffstat (limited to 'libs')
-rw-r--r--libs/http/luasrc/http/protocol.lua6
-rw-r--r--libs/http/luasrc/http/protocol/conditionals.lua15
-rw-r--r--libs/httpd/luasrc/httpd/handler/file.lua54
-rw-r--r--libs/httpd/luasrc/httpd/handler/luci.lua22
4 files changed, 67 insertions, 30 deletions
diff --git a/libs/http/luasrc/http/protocol.lua b/libs/http/luasrc/http/protocol.lua
index 205869a2d..67b425857 100644
--- a/libs/http/luasrc/http/protocol.lua
+++ b/libs/http/luasrc/http/protocol.lua
@@ -160,7 +160,7 @@ process_states['magic'] = function( msg, chunk, err )
end
end
end
-
+
-- Can't handle it
return nil, "Invalid HTTP message magic"
end
@@ -533,7 +533,7 @@ function header_source( sock )
local chunk, err, part = sock:receive("*l")
-- Line too long
- if chunk == nil then
+ if chunk == nil then
if err ~= "timeout" then
return nil, part
and "Line exceeds maximum allowed length["..part.."]"
@@ -779,11 +779,13 @@ end
-- Status codes
statusmsg = {
[200] = "OK",
+ [304] = "Not Modified",
[400] = "Bad Request",
[403] = "Forbidden",
[404] = "Not Found",
[405] = "Method Not Allowed",
[411] = "Length Required",
+ [412] = "Precondition Failed",
[500] = "Internal Server Error",
[503] = "Server Unavailable",
}
diff --git a/libs/http/luasrc/http/protocol/conditionals.lua b/libs/http/luasrc/http/protocol/conditionals.lua
index 0bff274cd..36f323a6e 100644
--- a/libs/http/luasrc/http/protocol/conditionals.lua
+++ b/libs/http/luasrc/http/protocol/conditionals.lua
@@ -21,7 +21,7 @@ local date = require("luci.http.protocol.date")
-- 14.19 / ETag
function mk_etag( stat )
if stat ~= nil then
- return string.format( "%x-%x-%x", stat.ino, stat.size, stat.mtime )
+ return string.format( '"%x-%x-%x"', stat.ino, stat.size, stat.mtime )
end
end
@@ -56,7 +56,10 @@ function if_modified_since( req, stat )
return true
end
- return false, 304
+ return false, 304, {
+ ["ETag"] = mk_etag( stat );
+ ["Last-Modified"] = date.to_http( stat.mtime )
+ }
end
return true
@@ -74,10 +77,10 @@ function if_none_match( req, stat )
if req.request_method == "get" or
req.request_method == "head"
then
- h['ETag'] = mk_etag( stat )
- h['Last-Modified'] = date.to_http( stat.mtime )
-
- return false, 304
+ return false, 304, {
+ ["ETag"] = mk_etag( stat );
+ ["Last-Modified"] = date.to_http( stat.mtime )
+ }
else
return false, 412
end
diff --git a/libs/httpd/luasrc/httpd/handler/file.lua b/libs/httpd/luasrc/httpd/handler/file.lua
index f553e8292..790ebdd66 100644
--- a/libs/httpd/luasrc/httpd/handler/file.lua
+++ b/libs/httpd/luasrc/httpd/handler/file.lua
@@ -31,10 +31,11 @@ function Simple.__init__(self, docroot, dirlist)
self.dirlist = dirlist and true or false
self.mime = luci.http.protocol.mime
self.date = luci.http.protocol.date
+ self.cond = luci.http.protocol.conditionals
end
function Simple.getfile(self, uri)
- local file = self.docroot .. uri:gsub("%.%./", "")
+ local file = self.docroot .. uri:gsub("%.%./+", "")
local stat = luci.fs.stat(file)
return file, stat
@@ -47,18 +48,45 @@ function Simple.handle_get(self, request, sourcein, sinkerr)
if stat.type == "regular" then
-- Generate Entity Tag
- local etag = luci.http.protocol.conditionals.mk_etag( stat )
-
- -- Send Response
- return Response(
- 200, {
- ["Date"] = self.date.to_http( os.time() );
- ["Last-Modified"] = self.date.to_http( stat.mtime );
- ["Content-Type"] = self.mime.to_mime( file );
- ["Content-Length"] = stat.size;
- ["ETag"] = etag;
- }
- ), ltn12.source.file(io.open(file))
+ local etag = self.cond.mk_etag( stat )
+
+ -- Check conditionals
+ local ok, code, hdrs
+
+ ok, code, hdrs = self.cond.if_modified_since( request, stat )
+ if ok then
+ ok, code, hdrs = self.cond.if_match( request, stat )
+ if ok then
+ ok, code, hdrs = self.cond.if_unmodified_since( request, stat )
+ if ok then
+ ok, code, hdrs = self.cond.if_none_match( request, stat )
+ if ok then
+ -- Send Response
+ return Response(
+ 200, {
+ ["Date"] = self.date.to_http( os.time() );
+ ["Last-Modified"] = self.date.to_http( stat.mtime );
+ ["Content-Type"] = self.mime.to_mime( file );
+ ["Content-Length"] = stat.size;
+ ["ETag"] = etag;
+ }
+ ), ltn12.source.file(io.open(file))
+ else
+ return Response( code, hdrs or { } ),
+ ltn12.source.empty()
+ end
+ else
+ return Response( code, hdrs or { } ),
+ ltn12.source.empty()
+ end
+ else
+ return Response( code, hdrs or { } ),
+ ltn12.source.empty()
+ end
+ else
+ return Response( code, hdrs or { } ),
+ ltn12.source.empty()
+ end
else
return self:failure(403, "Unable to transmit " .. stat.type .. " " .. file)
end
diff --git a/libs/httpd/luasrc/httpd/handler/luci.lua b/libs/httpd/luasrc/httpd/handler/luci.lua
index 49a9abc0d..4a83de1a4 100644
--- a/libs/httpd/luasrc/httpd/handler/luci.lua
+++ b/libs/httpd/luasrc/httpd/handler/luci.lua
@@ -1,7 +1,7 @@
--[[
HTTP server implementation for LuCI - luci handler
-(c) 2008 Steven Barth <steven@midlink.org>
+(c) 2008 Steven Barth <steven@midlink.org>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@ module("luci.httpd.handler.luci", package.seeall)
require("luci.dispatcher")
require("luci.http")
+require("luci.http.protocol.date")
require("ltn12")
Luci = luci.util.class(luci.httpd.module.Handler)
@@ -35,37 +36,37 @@ function Luci.handle_post(self, ...)
return self:handle_get(...)
end
-function Luci.handle_get(self, request, sourcein, sinkerr)
+function Luci.handle_get(self, request, sourcein, sinkerr)
local r = luci.http.Request(
request.env,
sourcein,
sinkerr
)
-
+
local res, id, data1, data2 = true, 0, nil, nil
local headers = {}
local status = 200
-
+
local x = coroutine.create(luci.dispatcher.httpdispatch)
while not id or id < 3 do
coroutine.yield()
-
+
res, id, data1, data2 = coroutine.resume(x, r)
-
+
if not res then
status = 500
headers["Content-Type"] = "text/plain"
local err = {id}
return Response( status, headers ), function() return table.remove(err) end
end
-
+
if id == 1 then
status = data1
elseif id == 2 then
headers[data1] = data2
end
end
-
+
local function iter()
local res, id, data = coroutine.resume(x)
if not res then
@@ -78,6 +79,9 @@ function Luci.handle_get(self, request, sourcein, sinkerr)
return data
end
end
-
+
+ headers["Expires"] = luci.http.protocol.date.to_http( os.time() )
+ headers["Date"] = headers["Expires"]
+
return Response(status, headers), iter
end