* libs/http: prepare support for RFC2616 / 14.24 - 14.28
This commit is contained in:
parent
3eefe8a8e2
commit
7f56bf9475
2 changed files with 118 additions and 11 deletions
111
libs/http/luasrc/http/protocol/conditionals.lua
Normal file
111
libs/http/luasrc/http/protocol/conditionals.lua
Normal file
|
@ -0,0 +1,111 @@
|
|||
--[[
|
||||
|
||||
HTTP protocol implementation for LuCI - RFC2616 / 14.19, 14.24 - 14.28
|
||||
(c) 2008 Freifunk Leipzig / Jo-Philipp Wich <xm@leipzig.freifunk.net>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
|
||||
]]--
|
||||
|
||||
module("luci.http.protocol.conditionals", package.seeall)
|
||||
|
||||
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 )
|
||||
end
|
||||
end
|
||||
|
||||
-- 14.24 / If-Match
|
||||
function if_match( req, stat )
|
||||
local h = req.headers
|
||||
local etag = mk_etag( stat )
|
||||
|
||||
-- Check for matching resource
|
||||
if type(h['If-Match']) == "string" then
|
||||
for ent in h['If-Match']:gmatch("([^, ]+)") do
|
||||
if ( ent == '*' or ent == etag ) and stat ~= nil then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false, 412
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
-- 14.25 / If-Modified-Since
|
||||
function if_modified_since( req, stat )
|
||||
local h = req.headers
|
||||
|
||||
-- Compare mtimes
|
||||
if type(h['If-Modified-Since']) == "string" then
|
||||
local since = date.to_unix( h['If-Modified-Since'] )
|
||||
|
||||
if stat == nil or since < stat.mtime then
|
||||
return true
|
||||
end
|
||||
|
||||
return false, 304
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
-- 14.26 / If-None-Match
|
||||
function if_none_match( req, stat )
|
||||
local h = req.headers
|
||||
local etag = mk_etag( stat )
|
||||
|
||||
-- Check for matching resource
|
||||
if type(h['If-None-Match']) == "string" then
|
||||
for ent in h['If-None-Match']:gmatch("([^, ]+)") do
|
||||
if ( ent == '*' or ent == etag ) and stat ~= nil then
|
||||
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
|
||||
else
|
||||
return false, 412
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
-- 14.27 / If-Range
|
||||
function if_range( req, stat )
|
||||
-- Sorry, no subranges (yet)
|
||||
return false, 412
|
||||
end
|
||||
|
||||
-- 14.28 / If-Unmodified-Since
|
||||
function if_unmodified_since( req, stat )
|
||||
local h = req.headers
|
||||
|
||||
-- Compare mtimes
|
||||
if type(h['If-Unmodified-Since']) == "string" then
|
||||
local since = date.to_unix( h['If-Unmodified-Since'] )
|
||||
|
||||
if stat ~= nil and since <= stat.mtime then
|
||||
return false, 412
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
|
@ -18,6 +18,7 @@ module("luci.httpd.handler.file", package.seeall)
|
|||
require("luci.httpd.module")
|
||||
require("luci.http.protocol.date")
|
||||
require("luci.http.protocol.mime")
|
||||
require("luci.http.protocol.conditionals")
|
||||
require("luci.fs")
|
||||
require("ltn12")
|
||||
|
||||
|
@ -39,28 +40,23 @@ function Simple.getfile(self, uri)
|
|||
return file, stat
|
||||
end
|
||||
|
||||
|
||||
function Simple._mk_etag(self, stat)
|
||||
return string.format( "%x-%x-%x", stat.ino, stat.size, stat.mtime )
|
||||
end
|
||||
|
||||
function Simple._cmp_etag(self, stat, etag)
|
||||
return ( self:_mk_etag(stat) == etag )
|
||||
end
|
||||
|
||||
|
||||
function Simple.handle_get(self, request, sourcein, sinkerr)
|
||||
local file, stat = self:getfile(request.env.PATH_INFO)
|
||||
|
||||
if stat then
|
||||
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"] = self:_mk_etag( stat );
|
||||
["ETag"] = etag;
|
||||
}
|
||||
), ltn12.source.file(io.open(file))
|
||||
else
|
||||
|
|
Loading…
Reference in a new issue