diff options
Diffstat (limited to 'lem/http/server.lua')
-rw-r--r-- | lem/http/server.lua | 196 |
1 files changed, 25 insertions, 171 deletions
diff --git a/lem/http/server.lua b/lem/http/server.lua index 378c8f6..cafab39 100644 --- a/lem/http/server.lua +++ b/lem/http/server.lua @@ -27,133 +27,12 @@ local format = string.format local concat = table.concat local remove = table.remove -local io = require 'lem.io' -require 'lem.http' +local io = require 'lem.io' + require 'lem.http' +local response = require 'lem.http.response' local M = {} -local status_string = { - -- 1xx Informational - [100] = '100 Continue', - [101] = '101 Switching Protocols', - [102] = '102 Processing', -- WebDAV - - -- 2xx Success - [200] = '200 OK', - [201] = '201 Created', - [202] = '202 Accepted', - [203] = '203 Non-Authoritative Information', - [204] = '204 No Content', - [205] = '205 Reset Content', - [206] = '206 Partial Content', - [207] = '207 Multi-Status', -- WebDAV - [208] = '208 Already Reported', -- WebDAV - [226] = '226 IM Used', - [230] = '230 Authentication Successfull', - - -- 3xx Redirection - [300] = '300 Multiple Choices', - [301] = '301 Moved Permanently', - [302] = '302 Found', - [303] = '303 See Other', - [304] = '304 Not Modified', - [305] = '305 Use Proxy', - [306] = '306 Switch Proxy', - [307] = '307 Temporary Redirect', - [308] = '308 Permanent Redirect', - - -- 4xx Client Error - [400] = '400 Bad Request', - [401] = '401 Unauthorized', - [402] = '402 Payment Required', - [403] = '403 Forbidden', - [404] = '404 Not Found', - [405] = '405 Method Not Allowed', - [406] = '406 Not Acceptable', - [407] = '407 Proxy Authentication Required', - [408] = '408 Request Timeout', - [409] = '409 Conflict', - [410] = '410 Gone', - [411] = '411 Length Required', - [412] = '412 Precondition Failed', - [413] = '413 Request Entity Too Large', - [414] = '414 Request-URI Too Long', - [415] = '415 Unsupported Media Type', - [416] = '416 Requested Range Not Satisfiable', - [417] = '417 Expectation Failed', - -- ... - [422] = '422 Unprocessable Entity', -- WebDAV - [423] = '423 Locked', -- WebDAV - [424] = '424 Failed Dependency', -- WebDAV - -- ... - [426] = '426 Upgrade Required', - [428] = '428 Precondition Required', - [429] = '429 Too Many Requests', - [431] = '431 Request Header Fields Too Large', - - -- 5xx Server Error - [500] = '500 Internal Server Error', - [501] = '501 Not Implemented', - [502] = '502 Bad Gateway', - [503] = '503 Service Unavailable', - [504] = '504 Gateway Timeout', - [505] = '505 HTTP Version Not Supported', - [506] = '506 Variant Also Negotiates', - [507] = '507 Insufficient Storage', -- WebDAV - [508] = '508 Loop Detected', -- WebDAV - -- ... - [510] = '510 Not Extended', - [511] = '511 Network Authentication Required', - [531] = '531 Access Denied', -} - -M.status_string = status_string - -function M.not_found(req, res) - if req.headers['expect'] ~= '100-continue' then - req:body() - end - - res.status = 404 - res.headers['Content-Type'] = 'text/html; charset=UTF-8' - res:add([[ -<?xml version="1.0" encoding="UTF-8"?> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> -<head> -<title>Not Found</title> -</head> -<body> -<h1>Not found</h1> -</body> -</html> -]]) -end - -function M.htmlerror(num, text) - local str = format([[ -<?xml version="1.0" encoding="UTF-8"?> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> -<head> -<title>%s</title> -</head> -<body> -<h1>%s</h1> -</body> -</html> -]], text, text) - return function(req, res) - res.status = num - res.headers['Content-Type'] = 'text/html; charset=UTF-8' - res.headers['Connection'] = 'close' - res:add(str) - end -end - -M.method_not_allowed = M.htmlerror(405, 'Method Not Allowed') -M.expectation_failed = M.htmlerror(417, 'Expectation Failed') -M.version_not_supported = M.htmlerror(505, 'HTTP Version Not Supported') -M.bad_request = M.htmlerror(400, 'Bad Request') - function M.debug() end do @@ -168,39 +47,20 @@ do end end -do - local Response = {} - Response.__index = Response - M.Response = Response - - function new_response(req) - local n = 0 - return setmetatable({ - headers = {}, - version = req.version, - add = function(self, fmt, first, ...) - n = n + 1 - if first then - self[n] = format(fmt, first, ...) - else - self[n] = fmt - end - end - }, Response) - end - - local function check_match(entry, req, res, ok, ...) - if not ok then return false end - local handler = entry[req.method] - if handler then - handler(req, res, ok, ...) - else - M.method_not_allowed(req, res) - end - return true +local function check_match(entry, req, res, ok, ...) + if not ok then return false end + local handler = entry[req.method] + if handler then + handler(req, res, ok, ...) + else + response.method_not_allowed(req, res) end + return true +end +do local urldecode = M.urldecode + local newresponse = response.new local function handleHTTP(self, client) repeat @@ -210,15 +70,15 @@ do req.path = urldecode(uri:match('^([^?]*)')) - local res = new_response(req) + local res = newresponse(req) if version ~= '1.0' and version ~= '1.1' then - M.version_not_supported(req, res) + response.version_not_supported(req, res) version = '1.1' else local expect = req.headers['expect'] if expect and expect ~= '100-continue' then - M.expectation_failed(req, res) + response.expectation_failed(req, res) else self.handler(req, res) end @@ -232,9 +92,9 @@ do close = true else self.debug('open', err) - res = new_response(req) + res = rewresponse(req) headers = res.headers - M.not_found(req, res) + response.not_found(req, res) end end @@ -272,27 +132,21 @@ do headers['Connection'] = 'close' end - local robe, i = {}, 1 + local rope = {} do local status = res.status if type(status) == 'number' then - status = status_string[status] + status = response.status_string[status] end - robe[1] = format('HTTP/%s %s\r\n', version, status) - end - - for k, v in pairs(headers) do - i = i + 1 - robe[i] = format('%s: %s\r\n', k, tostring(v)) + rope[1] = format('HTTP/%s %s\r\n', version, status) end - i = i + 1 - robe[i] = '\r\n' + res:appendheader(rope, 1) client:cork() - local ok, err = client:write(concat(robe)) + local ok, err = client:write(concat(rope)) if not ok then self.debug('write', err) break end if method ~= 'HEAD' then @@ -320,7 +174,7 @@ do Server.__index = Server M.Server = Server - function Server:run(handler) + function Server:run() return self.socket:autospawn(function(...) return handleHTTP(self, ...) end) end |