2023-01-25 17:01:01 +01:00
|
|
|
std = {}
|
|
|
|
require("silk.core.mimes")
|
2023-01-18 15:12:48 +01:00
|
|
|
|
|
|
|
RESPONSE_HEADER = {
|
2023-01-25 17:01:01 +01:00
|
|
|
status = 200,
|
|
|
|
header = {},
|
|
|
|
cookie = {},
|
|
|
|
sent = false
|
|
|
|
}
|
|
|
|
|
|
|
|
local http_status = {
|
|
|
|
[100] = "Continue",
|
|
|
|
[101] = "Switching Protocols",
|
|
|
|
[102] = "Processing",
|
|
|
|
[103] = "Early Hints",
|
|
|
|
|
|
|
|
[200] = "OK",
|
|
|
|
[201] = "Created",
|
|
|
|
[202] = "Accepted",
|
|
|
|
[203] = "Non-Authoritative Information",
|
|
|
|
[204] = "No Content",
|
|
|
|
[205] = "Reset Content",
|
|
|
|
[206] = "Partial Content",
|
|
|
|
[207] = "Multi-Status",
|
|
|
|
[208] = "Already Reported",
|
|
|
|
[226] = "IM Used",
|
|
|
|
|
|
|
|
[300] = "Multiple Choices",
|
|
|
|
[301] = "Moved Permanently",
|
|
|
|
[302] = "Found",
|
|
|
|
[303] = "See Other",
|
|
|
|
[304] = "Not Modified",
|
|
|
|
[305] = "Use Proxy",
|
|
|
|
[306] = "Switch Proxy",
|
|
|
|
[307] = "Temporary Redirect",
|
|
|
|
[308] = "Permanent Redirect",
|
|
|
|
|
|
|
|
[400] = "Bad Request",
|
|
|
|
[401] = "Unauthorized",
|
|
|
|
[402] = "Payment Required",
|
|
|
|
[403] = "Forbidden",
|
|
|
|
[404] = "Not Found",
|
|
|
|
[405] = "Method Not Allowed",
|
|
|
|
[406] = "Not Acceptable",
|
|
|
|
[407] = "Proxy Authentication Required",
|
|
|
|
[408] = "Request Timeout",
|
|
|
|
[409] = "Conflict",
|
|
|
|
[410] = "Gone",
|
|
|
|
[411] = "Length Required",
|
|
|
|
[412] = "Precondition Failed",
|
|
|
|
[413] = "Payload Too Large",
|
|
|
|
[414] = "URI Too Long",
|
|
|
|
[415] = "Unsupported Media Type",
|
|
|
|
[416] = "Range Not Satisfiable",
|
|
|
|
[417] = "Expectation Failed",
|
|
|
|
[421] = "Misdirected Request",
|
|
|
|
[422] = "Unprocessable Entity",
|
|
|
|
[423] = "Locked",
|
|
|
|
[424] = "Failed Dependency",
|
|
|
|
[425] = "Too Early",
|
|
|
|
[426] = "Upgrade Required",
|
|
|
|
[428] = "Precondition Required",
|
|
|
|
[429] = "Too Many Requests",
|
|
|
|
[431] = "Request Header Fields Too Large",
|
|
|
|
[451] = "Unavailable For Legal Reasons",
|
|
|
|
|
|
|
|
[500] = "Internal Server Error",
|
|
|
|
[501] = "Not Implemented",
|
|
|
|
[502] = "Bad Gateway",
|
|
|
|
[503] = "Service Unavailable",
|
|
|
|
[504] = "Gateway Timeout",
|
|
|
|
[505] = "HTTP Version Not Supported",
|
|
|
|
[506] = "Variant Also Negotiates",
|
|
|
|
[507] = "Insufficient Storage",
|
|
|
|
[508] = "Loop Detected",
|
|
|
|
[510] = "Not Extended",
|
|
|
|
[511] = "Network Authentication Required"
|
2023-01-18 15:12:48 +01:00
|
|
|
}
|
2023-01-25 17:01:01 +01:00
|
|
|
setmetatable(http_status, {
|
|
|
|
__index = function(this, key)
|
|
|
|
return "Unofficial Status"
|
|
|
|
end
|
|
|
|
})
|
2023-01-18 15:12:48 +01:00
|
|
|
|
|
|
|
function std.status(code)
|
2023-01-25 17:01:01 +01:00
|
|
|
RESPONSE_HEADER.status = code
|
2023-01-18 15:12:48 +01:00
|
|
|
end
|
|
|
|
|
2023-01-25 17:01:01 +01:00
|
|
|
function std.custom_header(k, v)
|
|
|
|
std.header(k, v)
|
2023-01-18 15:12:48 +01:00
|
|
|
end
|
|
|
|
|
2023-01-25 17:01:01 +01:00
|
|
|
function std.header(k, v)
|
|
|
|
RESPONSE_HEADER.header[k] = v
|
2023-01-18 15:12:48 +01:00
|
|
|
end
|
2023-01-25 17:01:01 +01:00
|
|
|
|
|
|
|
function std.header_flush()
|
|
|
|
-- send out status
|
|
|
|
echo("Status: ", RESPONSE_HEADER.status, " ", http_status[RESPONSE_HEADER.status], "\r\n")
|
|
|
|
-- send out header
|
|
|
|
for key, val in pairs(RESPONSE_HEADER.header) do
|
|
|
|
echo(key, ": ", val, "\r\n")
|
|
|
|
end
|
|
|
|
-- send out cookie
|
|
|
|
for key, val in ipairs(RESPONSE_HEADER.cookie) do
|
|
|
|
echo("Set-Cookie: ", val, "\r\n")
|
|
|
|
end
|
|
|
|
echo("\r\n")
|
|
|
|
RESPONSE_HEADER.sent = true
|
|
|
|
RESPONSE_HEADER.header = {}
|
|
|
|
RESPONSE_HEADER.cookie = {}
|
2023-01-18 15:12:48 +01:00
|
|
|
end
|
|
|
|
|
2023-01-25 17:01:01 +01:00
|
|
|
function std.setCookie(...)
|
|
|
|
local args = table.pack(...)
|
|
|
|
cookie = table.concat(args,";")
|
|
|
|
RESPONSE_HEADER.cookie[#RESPONSE_HEADER.cookie + 1] = cookie
|
2023-01-18 15:12:48 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
function std.error(status, msg)
|
2023-01-25 17:01:01 +01:00
|
|
|
std.status(status)
|
|
|
|
std.header("Content-Type", "text/html")
|
|
|
|
std.header_flush()
|
|
|
|
echo(string.format("<HTML><HEAD><TITLE>%s</TITLE></HEAD><BODY><h2>%s</h2></BODY></HTML>",msg, msg))
|
2023-01-18 15:12:48 +01:00
|
|
|
end
|
2023-01-25 17:01:01 +01:00
|
|
|
|
2023-01-18 15:12:48 +01:00
|
|
|
function std.unknow(s)
|
2023-01-25 17:01:01 +01:00
|
|
|
std.error(404, "Unknown request")
|
2023-01-18 15:12:48 +01:00
|
|
|
end
|
|
|
|
|
2023-01-25 17:01:01 +01:00
|
|
|
function std.f(path)
|
|
|
|
fcgio:send_file(path)
|
|
|
|
end
|
2023-01-18 15:12:48 +01:00
|
|
|
|
2023-01-26 02:27:22 +01:00
|
|
|
function std.t(...)
|
|
|
|
echo(...)
|
|
|
|
end
|
|
|
|
|
|
|
|
|
2023-01-18 15:12:48 +01:00
|
|
|
function std.html()
|
2023-01-25 17:01:01 +01:00
|
|
|
std.header("Content-Type", "text/html; charset=utf-8")
|
|
|
|
std.header_flush()
|
2023-01-18 15:12:48 +01:00
|
|
|
end
|
2023-01-25 17:01:01 +01:00
|
|
|
|
2023-01-18 15:12:48 +01:00
|
|
|
function std.text()
|
2023-01-25 17:01:01 +01:00
|
|
|
std.header("Content-Type", "text/plain; charset=utf-8")
|
|
|
|
std.header_flush()
|
2023-01-18 15:12:48 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
function std.json()
|
2023-01-25 17:01:01 +01:00
|
|
|
std.header("Content-Type", "application/json; charset=utf-8")
|
|
|
|
std.header_flush()
|
2023-01-18 15:12:48 +01:00
|
|
|
end
|
2023-01-25 17:01:01 +01:00
|
|
|
|
2023-01-18 15:12:48 +01:00
|
|
|
function std.jpeg()
|
2023-01-25 17:01:01 +01:00
|
|
|
std.header("Content-Type", "image/jpeg")
|
|
|
|
std.header_flush()
|
2023-01-18 15:12:48 +01:00
|
|
|
end
|
2023-01-25 17:01:01 +01:00
|
|
|
|
2023-01-18 15:12:48 +01:00
|
|
|
function std.octstream(s)
|
2023-01-25 17:01:01 +01:00
|
|
|
std.header("Content-Type", "application/octet-stream")
|
|
|
|
std.header("Content-Disposition", 'attachment; filename="' .. s .. '"')
|
|
|
|
std.header_flush()
|
|
|
|
end
|
|
|
|
|
|
|
|
function std.is_file(f)
|
|
|
|
return ulib.is_dir(f) == false
|
|
|
|
end
|
|
|
|
|
|
|
|
-- TODO provide web socket support
|
|
|
|
-- use coroutine to read socket message
|
2023-01-18 15:12:48 +01:00
|
|
|
std.ws = {}
|
|
|
|
function std.ws.header()
|
2023-01-25 17:01:01 +01:00
|
|
|
local h = std.ws_header(HTTP_REQUEST.id)
|
|
|
|
if (h) then
|
|
|
|
return h -- std.readOnly(h)
|
|
|
|
else
|
|
|
|
return nil
|
|
|
|
end
|
2023-01-18 15:12:48 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
function std.ws.read(h)
|
2023-01-25 17:01:01 +01:00
|
|
|
return std.ws_read(HTTP_REQUEST.id, h)
|
2023-01-18 15:12:48 +01:00
|
|
|
end
|
|
|
|
function std.ws.swrite(s)
|
2023-01-25 17:01:01 +01:00
|
|
|
std.ws_t(HTTP_REQUEST.id, s)
|
2023-01-18 15:12:48 +01:00
|
|
|
end
|
|
|
|
function std.ws.fwrite(s)
|
2023-01-25 17:01:01 +01:00
|
|
|
std.ws_f(HTTP_REQUEST.id, s)
|
2023-01-18 15:12:48 +01:00
|
|
|
end
|
|
|
|
function std.ws.write_bytes(arr)
|
2023-01-25 17:01:01 +01:00
|
|
|
std.ws_b(HTTP_REQUEST.id, arr)
|
2023-01-18 15:12:48 +01:00
|
|
|
end
|
|
|
|
function std.ws.enable()
|
2023-01-25 17:01:01 +01:00
|
|
|
return HTTP_REQUEST ~= nil and HTTP_REQUEST.request["__web_socket__"] == "1"
|
2023-01-18 15:12:48 +01:00
|
|
|
end
|
|
|
|
function std.ws.close(code)
|
2023-01-25 17:01:01 +01:00
|
|
|
std.ws_close(HTTP_REQUEST.id, code)
|
2023-01-18 15:12:48 +01:00
|
|
|
end
|
|
|
|
std.ws.TEXT = 1
|
|
|
|
std.ws.BIN = 2
|
|
|
|
std.ws.CLOSE = 8
|