local hlib = {} local fmt = string.format local g_version = "1.1" local g_status_msg = { [100] = "Continue", [101] = "Switching Protocols", [102] = "Processing", [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", [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] = "Request-URI Too Long", [415] = "Unsupported Media Type", [416] = "Requested Range Not Satisfiable", [417] = "Expectation Failed", [418] = "I'm a teapot", [421] = "Misdirected Request", [422] = "Unprocessable Entity", [423] = "Locked", [424] = "Failed Dependency", [426] = "Upgrade Required", [428] = "Precondition Required", [429] = "Too Many Requests", [431] = "Request Header Fields Too Large", [444] = "Connection Closed Without Response", [451] = "Unavailable For Legal Reasons", [499] = "Client Closed Request", [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", [599] = "Network Connect Timeout Error", } function push_headers(headers, add) for k,v in pairs(add) do headers[k] = v end return headers end function get_content_length(body) return {["Content-Length"] = #body+1} end function get_content_type(body) return {["Content-Type"] = "text/html"} end local header_functions = { get_content_length, get_content_type } function hlib.parse_request(r) local request = { method = nil, path = nil, version = nil, headers = {} } local lines = string.gmatch(r, "[^\n]+") local head_msg = lines() local _, _, method, path, version = string.find(head_msg, "(%u+) ([%w/]+) ([%w/%.]+)") request.method = method request.path = path request.version = version for line in lines do local _, _, a, b = string.find(line, "([%w-]+): (.+)") if a then request.headers[a] = b end end return request end function hlib.response(path, status, body) local resp = { version = fmt("HTTP/%s", g_version), status = status, status_msg = g_status_msg[status], body = body, headers = {} } for k,v in pairs(header_functions) do resp.headers = push_headers(resp.headers, v(body)) end local r = fmt( [[%s %s %s Content-Length: %d %s ]], resp.version, resp.status, resp.status_msg, #resp.body+1, resp.body) return r end return hlib