-- skyweave/request.lua local json = require("json") -- Assuming json.lua is in a standard Lua path e.g. /usr/lib/lua -- Removed local parse_query_string function, will use utils.parse_query_string -- local function parse_query_string(query_string) -- local params = {} -- if not query_string or query_string == "" then return params end -- -- for pair in query_string:gmatch("[^&]+") do -- local key, value = pair:match("([^=]+)=?(.*)") -- if key then -- key = key:gsub("+", " "):gsub("%%(%x%x)", function(h) return string.char(tonumber(h, 16)) end) -- value = value or "" -- Ensure value is a string, even if empty after '=' -- value = value:gsub("+", " "):gsub("%%(%x%x)", function(h) return string.char(tonumber(h, 16)) end) -- params[key] = value -- end -- end -- return params -- end local utils = require("skyweave.utils") -- Updated path local request_module = {} function request_module.create_request_context() local request = {} request.method = os.getenv("REQUEST_METHOD") or "GET" -- Default to GET if not set local query_string_env = os.getenv("QUERY_STRING") or "" request.query = utils.parse_query_string(query_string_env) -- PATH_INFO is the part of the URL after the script name and before the query string. -- e.g. /cgi-bin/skyweave.lua/some/path?foo=bar -> /some/path -- This is dependent on Nginx configuration (e.g. using fastcgi_split_path_info). -- If not properly set by Nginx, it might be nil or empty. request.path = os.getenv("PATH_INFO") or "/" if request.path == "" then request.path = "/" end request.headers = {} -- Populate headers using os.getenv for specific, known CGI variables local content_type_env = os.getenv("CONTENT_TYPE") -- Use different var name to avoid conflict with request.headers.content-type if content_type_env then request.headers["content-type"] = content_type_env end local user_agent = os.getenv("HTTP_USER_AGENT") if user_agent then request.headers["user-agent"] = user_agent end local accept_header = os.getenv("HTTP_ACCEPT") if accept_header then request.headers["accept"] = accept_header end -- Add other common headers if needed, for example: -- local accept_encoding = os.getenv("HTTP_ACCEPT_ENCODING") -- if accept_encoding then request.headers["accept-encoding"] = accept_encoding end -- -- local accept_language = os.getenv("HTTP_ACCEPT_LANGUAGE") -- if accept_language then request.headers["accept-language"] = accept_language end -- -- local referer = os.getenv("HTTP_REFERER") -- if referer then request.headers["referer"] = referer end -- -- Note: CONTENT_LENGTH is retrieved later via os.getenv("CONTENT_LENGTH") specifically for body processing. -- It is not typically added to this general request.headers table unless other logic specifically needs it there. request.raw_body = nil request.body = nil request.body_parse_error = nil if request.method == "POST" or request.method == "PUT" or request.method == "PATCH" then local content_length_str = os.getenv("CONTENT_LENGTH") local content_length = tonumber(content_length_str or 0) if content_length and content_length > 0 then -- Removed: io.stdin:setvbuf("binary") -- Not supported/needed for JSON POST or general text POST request.raw_body = io.stdin:read(content_length) -- Try to parse if content type suggests JSON and JSON lib is available local content_type = request.headers["content-type"] or "" if json and content_type:lower():match("application/json") then if request.raw_body and request.raw_body ~= "" then local success, decoded_or_error = pcall(json.decode, request.raw_body) if success then request.body = decoded_or_error else request.body_parse_error = "JSON decode error: " .. tostring(decoded_or_error) end else request.body_parse_error = "Empty body received with application/json Content-Type" end else -- If not JSON or no JSON lib, body remains nil, raw_body has the content. -- Handlers can inspect raw_body if they expect other content types. if not json and content_type:lower():match("application/json") then request.body_parse_error = "Received JSON Content-Type but no JSON library is loaded." end end end end return request end return request_module