mirror of
https://github.com/coolsnowwolf/luci
synced 2025-01-07 07:06:41 +08:00
add luci-lib-httpprotoutils
This commit is contained in:
parent
3a2a6186ed
commit
411f655970
14
libs/luci-lib-httpprotoutils/Makefile
Normal file
14
libs/luci-lib-httpprotoutils/Makefile
Normal file
@ -0,0 +1,14 @@
|
||||
#
|
||||
# Copyright (C) 2018 The LuCI Team <luci@lists.subsignal.org>
|
||||
#
|
||||
# This is free software, licensed under the Apache License, Version 2.0 .
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
LUCI_TITLE:=HTTP protocol utility functions
|
||||
LUCI_DEPENDS:=+luci-base
|
||||
|
||||
include ../../luci.mk
|
||||
|
||||
# call BuildPackage - OpenWrt buildroot signature
|
110
libs/luci-lib-httpprotoutils/luasrc/http/conditionals.lua
Normal file
110
libs/luci-lib-httpprotoutils/luasrc/http/conditionals.lua
Normal file
@ -0,0 +1,110 @@
|
||||
-- Copyright 2008 Freifunk Leipzig / Jo-Philipp Wich <jow@openwrt.org>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
-- This class provides basic ETag handling and implements most of the
|
||||
-- conditional HTTP/1.1 headers specified in RFC2616 Sct. 14.24 - 14.28 .
|
||||
module("luci.http.conditionals", package.seeall)
|
||||
|
||||
local date = require("luci.http.date")
|
||||
|
||||
|
||||
function mk_etag( stat )
|
||||
if stat ~= nil then
|
||||
return string.format( '"%x-%x-%x"', stat.ino, stat.size, stat.mtime )
|
||||
end
|
||||
end
|
||||
|
||||
-- Test whether the given message object contains an "If-Match" header and
|
||||
-- compare it against the given stat object.
|
||||
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
|
||||
|
||||
-- Test whether the given message object contains an "If-Modified-Since" header
|
||||
-- and compare it against the given stat object.
|
||||
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, {
|
||||
["ETag"] = mk_etag( stat );
|
||||
["Date"] = date.to_http( os.time() );
|
||||
["Last-Modified"] = date.to_http( stat.mtime )
|
||||
}
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
-- Test whether the given message object contains an "If-None-Match" header and
|
||||
-- compare it against the given stat object.
|
||||
function if_none_match( req, stat )
|
||||
local h = req.headers
|
||||
local etag = mk_etag( stat )
|
||||
local method = req.env and req.env.REQUEST_METHOD or "GET"
|
||||
|
||||
-- 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 method == "GET" or method == "HEAD" then
|
||||
return false, 304, {
|
||||
["ETag"] = etag;
|
||||
["Date"] = date.to_http( os.time() );
|
||||
["Last-Modified"] = date.to_http( stat.mtime )
|
||||
}
|
||||
else
|
||||
return false, 412
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
-- The If-Range header is currently not implemented due to the lack of general
|
||||
-- byte range stuff in luci.http.protocol . This function will always return
|
||||
-- false, 412 to indicate a failed precondition.
|
||||
function if_range( req, stat )
|
||||
-- Sorry, no subranges (yet)
|
||||
return false, 412
|
||||
end
|
||||
|
||||
-- Test whether the given message object contains an "If-Unmodified-Since"
|
||||
-- header and compare it against the given stat object.
|
||||
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
|
85
libs/luci-lib-httpprotoutils/luasrc/http/conditionals.luadoc
Normal file
85
libs/luci-lib-httpprotoutils/luasrc/http/conditionals.luadoc
Normal file
@ -0,0 +1,85 @@
|
||||
---[[
|
||||
LuCI http protocol implementation - HTTP/1.1 bits.
|
||||
|
||||
This class provides basic ETag handling and implements most of the
|
||||
conditional HTTP/1.1 headers specified in RFC2616 Sct. 14.24 - 14.28 .
|
||||
]]
|
||||
module "luci.http.conditionals"
|
||||
|
||||
---[[
|
||||
Implement 14.19 / ETag.
|
||||
|
||||
@class function
|
||||
@name mk_etag
|
||||
@param stat A file.stat structure
|
||||
@return String containing the generated tag suitable for ETag headers
|
||||
]]
|
||||
|
||||
---[[
|
||||
14.24 / If-Match
|
||||
|
||||
Test whether the given message object contains an "If-Match" header and
|
||||
compare it against the given stat object.
|
||||
@class function
|
||||
@name if_match
|
||||
@param req HTTP request message object
|
||||
@param stat A file.stat object
|
||||
@return Boolean indicating whether the precondition is ok
|
||||
@return Alternative status code if the precondition failed
|
||||
]]
|
||||
|
||||
---[[
|
||||
14.25 / If-Modified-Since
|
||||
|
||||
Test whether the given message object contains an "If-Modified-Since" header
|
||||
and compare it against the given stat object.
|
||||
@class function
|
||||
@name if_modified_since
|
||||
@param req HTTP request message object
|
||||
@param stat A file.stat object
|
||||
@return Boolean indicating whether the precondition is ok
|
||||
@return Alternative status code if the precondition failed
|
||||
@return Table containing extra HTTP headers if the precondition failed
|
||||
]]
|
||||
|
||||
---[[
|
||||
14.26 / If-None-Match
|
||||
|
||||
Test whether the given message object contains an "If-None-Match" header and
|
||||
compare it against the given stat object.
|
||||
@class function
|
||||
@name if_none_match
|
||||
@param req HTTP request message object
|
||||
@param stat A file.stat object
|
||||
@return Boolean indicating whether the precondition is ok
|
||||
@return Alternative status code if the precondition failed
|
||||
@return Table containing extra HTTP headers if the precondition failed
|
||||
]]
|
||||
|
||||
---[[
|
||||
14.27 / If-Range
|
||||
|
||||
The If-Range header is currently not implemented due to the lack of general
|
||||
byte range stuff in luci.http.protocol . This function will always return
|
||||
false, 412 to indicate a failed precondition.
|
||||
@class function
|
||||
@name if_range
|
||||
@param req HTTP request message object
|
||||
@param stat A file.stat object
|
||||
@return Boolean indicating whether the precondition is ok
|
||||
@return Alternative status code if the precondition failed
|
||||
]]
|
||||
|
||||
---[[
|
||||
14.28 / If-Unmodified-Since
|
||||
|
||||
Test whether the given message object contains an "If-Unmodified-Since"
|
||||
header and compare it against the given stat object.
|
||||
@class function
|
||||
@name if_unmodified_since
|
||||
@param req HTTP request message object
|
||||
@param stat A file.stat object
|
||||
@return Boolean indicating whether the precondition is ok
|
||||
@return Alternative status code if the precondition failed
|
||||
]]
|
||||
|
87
libs/luci-lib-httpprotoutils/luasrc/http/date.lua
Normal file
87
libs/luci-lib-httpprotoutils/luasrc/http/date.lua
Normal file
@ -0,0 +1,87 @@
|
||||
-- Copyright 2008 Freifunk Leipzig / Jo-Philipp Wich <jow@openwrt.org>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
-- This class contains functions to parse, compare and format http dates.
|
||||
module("luci.http.date", package.seeall)
|
||||
|
||||
require("luci.sys.zoneinfo")
|
||||
|
||||
|
||||
MONTHS = {
|
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug",
|
||||
"Sep", "Oct", "Nov", "Dec"
|
||||
}
|
||||
|
||||
function tz_offset(tz)
|
||||
|
||||
if type(tz) == "string" then
|
||||
|
||||
-- check for a numeric identifier
|
||||
local s, v = tz:match("([%+%-])([0-9]+)")
|
||||
if s == '+' then s = 1 else s = -1 end
|
||||
if v then v = tonumber(v) end
|
||||
|
||||
if s and v then
|
||||
return s * 60 * ( math.floor( v / 100 ) * 60 + ( v % 100 ) )
|
||||
|
||||
-- lookup symbolic tz
|
||||
elseif luci.sys.zoneinfo.OFFSET[tz:lower()] then
|
||||
return luci.sys.zoneinfo.OFFSET[tz:lower()]
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- bad luck
|
||||
return 0
|
||||
end
|
||||
|
||||
function to_unix(date)
|
||||
|
||||
local wd, day, mon, yr, hr, min, sec, tz = date:match(
|
||||
"([A-Z][a-z][a-z]), ([0-9]+) " ..
|
||||
"([A-Z][a-z][a-z]) ([0-9]+) " ..
|
||||
"([0-9]+):([0-9]+):([0-9]+) " ..
|
||||
"([A-Z0-9%+%-]+)"
|
||||
)
|
||||
|
||||
if day and mon and yr and hr and min and sec then
|
||||
-- find month
|
||||
local month = 1
|
||||
for i = 1, 12 do
|
||||
if MONTHS[i] == mon then
|
||||
month = i
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
-- convert to epoch time
|
||||
return tz_offset(tz) + os.time( {
|
||||
year = yr,
|
||||
month = month,
|
||||
day = day,
|
||||
hour = hr,
|
||||
min = min,
|
||||
sec = sec
|
||||
} )
|
||||
end
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
function to_http(time)
|
||||
return os.date( "%a, %d %b %Y %H:%M:%S GMT", time )
|
||||
end
|
||||
|
||||
function compare(d1, d2)
|
||||
|
||||
if d1:match("[^0-9]") then d1 = to_unix(d1) end
|
||||
if d2:match("[^0-9]") then d2 = to_unix(d2) end
|
||||
|
||||
if d1 == d2 then
|
||||
return 0
|
||||
elseif d1 < d2 then
|
||||
return -1
|
||||
else
|
||||
return 1
|
||||
end
|
||||
end
|
46
libs/luci-lib-httpprotoutils/luasrc/http/date.luadoc
Normal file
46
libs/luci-lib-httpprotoutils/luasrc/http/date.luadoc
Normal file
@ -0,0 +1,46 @@
|
||||
---[[
|
||||
LuCI http protocol implementation - date helper class.
|
||||
|
||||
This class contains functions to parse, compare and format http dates.
|
||||
]]
|
||||
module "luci.http.date"
|
||||
|
||||
---[[
|
||||
Return the time offset in seconds between the UTC and given time zone.
|
||||
|
||||
@class function
|
||||
@name tz_offset
|
||||
@param tz Symbolic or numeric timezone specifier
|
||||
@return Time offset to UTC in seconds
|
||||
]]
|
||||
|
||||
---[[
|
||||
Parse given HTTP date string and convert it to unix epoch time.
|
||||
|
||||
@class function
|
||||
@name to_unix
|
||||
@param data String containing the date
|
||||
@return Unix epoch time
|
||||
]]
|
||||
|
||||
---[[
|
||||
Convert the given unix epoch time to valid HTTP date string.
|
||||
|
||||
@class function
|
||||
@name to_http
|
||||
@param time Unix epoch time
|
||||
@return String containing the formatted date
|
||||
]]
|
||||
|
||||
---[[
|
||||
Compare two dates which can either be unix epoch times or HTTP date strings.
|
||||
|
||||
@class function
|
||||
@name compare
|
||||
@param d1 The first date or epoch time to compare
|
||||
@param d2 The first date or epoch time to compare
|
||||
@return -1 - if d1 is lower then d2
|
||||
@return 0 - if both dates are equal
|
||||
@return 1 - if d1 is higher then d2
|
||||
]]
|
||||
|
78
libs/luci-lib-httpprotoutils/luasrc/http/mime.lua
Normal file
78
libs/luci-lib-httpprotoutils/luasrc/http/mime.lua
Normal file
@ -0,0 +1,78 @@
|
||||
-- Copyright 2008 Freifunk Leipzig / Jo-Philipp Wich <jow@openwrt.org>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
-- This class provides functions to guess mime types from file extensions and
|
||||
-- vice versa.
|
||||
module("luci.http.mime", package.seeall)
|
||||
|
||||
require("luci.util")
|
||||
|
||||
MIME_TYPES = {
|
||||
["txt"] = "text/plain";
|
||||
["js"] = "text/javascript";
|
||||
["css"] = "text/css";
|
||||
["htm"] = "text/html";
|
||||
["html"] = "text/html";
|
||||
["patch"] = "text/x-patch";
|
||||
["c"] = "text/x-csrc";
|
||||
["h"] = "text/x-chdr";
|
||||
["o"] = "text/x-object";
|
||||
["ko"] = "text/x-object";
|
||||
|
||||
["bmp"] = "image/bmp";
|
||||
["gif"] = "image/gif";
|
||||
["png"] = "image/png";
|
||||
["jpg"] = "image/jpeg";
|
||||
["jpeg"] = "image/jpeg";
|
||||
["svg"] = "image/svg+xml";
|
||||
|
||||
["zip"] = "application/zip";
|
||||
["pdf"] = "application/pdf";
|
||||
["xml"] = "application/xml";
|
||||
["xsl"] = "application/xml";
|
||||
["doc"] = "application/msword";
|
||||
["ppt"] = "application/vnd.ms-powerpoint";
|
||||
["xls"] = "application/vnd.ms-excel";
|
||||
["odt"] = "application/vnd.oasis.opendocument.text";
|
||||
["odp"] = "application/vnd.oasis.opendocument.presentation";
|
||||
["pl"] = "application/x-perl";
|
||||
["sh"] = "application/x-shellscript";
|
||||
["php"] = "application/x-php";
|
||||
["deb"] = "application/x-deb";
|
||||
["iso"] = "application/x-cd-image";
|
||||
["tgz"] = "application/x-compressed-tar";
|
||||
|
||||
["mp3"] = "audio/mpeg";
|
||||
["ogg"] = "audio/x-vorbis+ogg";
|
||||
["wav"] = "audio/x-wav";
|
||||
|
||||
["mpg"] = "video/mpeg";
|
||||
["mpeg"] = "video/mpeg";
|
||||
["avi"] = "video/x-msvideo";
|
||||
}
|
||||
|
||||
-- "application/octet-stream" if the extension is unknown.
|
||||
function to_mime(filename)
|
||||
if type(filename) == "string" then
|
||||
local ext = filename:match("[^%.]+$")
|
||||
|
||||
if ext and MIME_TYPES[ext:lower()] then
|
||||
return MIME_TYPES[ext:lower()]
|
||||
end
|
||||
end
|
||||
|
||||
return "application/octet-stream"
|
||||
end
|
||||
|
||||
-- given mime-type is unknown.
|
||||
function to_ext(mimetype)
|
||||
if type(mimetype) == "string" then
|
||||
for ext, type in luci.util.kspairs( MIME_TYPES ) do
|
||||
if type == mimetype then
|
||||
return ext
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
34
libs/luci-lib-httpprotoutils/luasrc/http/mime.luadoc
Normal file
34
libs/luci-lib-httpprotoutils/luasrc/http/mime.luadoc
Normal file
@ -0,0 +1,34 @@
|
||||
---[[
|
||||
LuCI http protocol implementation - mime helper class.
|
||||
|
||||
This class provides functions to guess mime types from file extensions and
|
||||
vice versa.
|
||||
]]
|
||||
module "luci.http.mime"
|
||||
|
||||
---[[
|
||||
MIME mapping table containg extension - mimetype relations.
|
||||
|
||||
@class table
|
||||
]]
|
||||
|
||||
---[[
|
||||
Extract extension from a filename and return corresponding mime-type or
|
||||
|
||||
"application/octet-stream" if the extension is unknown.
|
||||
@class function
|
||||
@name to_mime
|
||||
@param filename The filename for which the mime type is guessed
|
||||
@return String containign the determined mime type
|
||||
]]
|
||||
|
||||
---[[
|
||||
Return corresponding extension for a given mime type or nil if the
|
||||
|
||||
given mime-type is unknown.
|
||||
@class function
|
||||
@name to_ext
|
||||
@param mimetype The mimetype to retrieve the extension from
|
||||
@return String with the extension or nil for unknown type
|
||||
]]
|
||||
|
Loading…
Reference in New Issue
Block a user