forked from marcoskirsch/nodemcu-httpserver
- Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhttpserver-request.lua
More file actions
Latest commit
120 lines (105 loc) · 3.46 KB
/
Copy pathhttpserver-request.lua
File metadata and controls
120 lines (105 loc) · 3.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
-- httpserver-request
-- Part of nodemcu-httpserver, parses incoming client requests.
-- Author: Marcos Kirsch
localfunctionvalidateMethod(method)
localhttpMethods= {GET=true, HEAD=true, POST=true, PUT=true, DELETE=true, TRACE=true, OPTIONS=true, CONNECT=true, PATCH=true}
-- default for non-existent attributes returns nil, which evaluates to false
returnhttpMethods[method]
end
localfunctionuriToFilename(uri)
return"http/" ..string.sub(uri, 2, -1)
end
localfunctionhex_to_char(x)
returnstring.char(tonumber(x, 16))
end
localfunctionuri_decode(input)
returninput:gsub("%+", ""):gsub("%%(%x%x)", hex_to_char)
end
localfunctionparseArgs(args)
localr= {}; i=1
ifargs==nilorargs=="" thenreturnrend
forarginstring.gmatch(args, "([^&]+)") do
localname, value=string.match(arg, "(.*)=(.*)")
ifname~=nilthenr[name] =uri_decode(value) end
i=i+1
end
returnr
end
localfunctionparseFormData(body)
localdata= {}
print("Parsing Form Data")
forkvinbody.gmatch(body, "%s*&?([^=]+=[^&]+)") do
localkey, value=string.match(kv, "(.*)=(.*)")
print("Parsed: " ..key.." => " ..value)
data[key] =uri_decode(value)
end
returndata
end
localfunctiongetRequestData(payload)
localrequestData
returnfunction ()
print("Getting Request Data")
ifrequestDatathen
returnrequestData
else
localmimeType=string.match(payload, "Content%-Type: (%S+)\r\n")
localbody_start=payload:find("\r\n\r\n", 1, true)
localbody=payload:sub(body_start, #payload)
payload=nil
collectgarbage()
-- print("mimeType = [" .. mimeType .. "]")
ifmimeType=="application/json" then
print("JSON: " ..body)
requestData=cjson.decode(body)
elseifmimeType=="application/x-www-form-urlencoded" then
requestData=parseFormData(body)
else
requestData= {}
end
returnrequestData
end
end
end
localfunctionparseUri(uri)
localr= {}
localfilename
localext
localfullExt= {}
ifuri==nilthenreturnrend
ifuri=="/" thenuri="/index.html" end
questionMarkPos, b, c, d, e, f=uri:find("?")
ifquestionMarkPos==nilthen
r.file=uri:sub(1, questionMarkPos)
r.args= {}
else
r.file=uri:sub(1, questionMarkPos-1)
r.args=parseArgs(uri:sub(questionMarkPos+1, #uri))
end
filename=r.file
whilefilename:match("%.") do
filename,ext=filename:match("(.+)%.(.+)")
table.insert(fullExt,1,ext)
end
if#fullExt>1andfullExt[#fullExt] =='gz' then
r.ext=fullExt[#fullExt-1]
r.isGzipped=true
elseif#fullExt>=1then
r.ext=fullExt[#fullExt]
end
r.isScript=r.ext=="lua" orr.ext=="lc"
r.file=uriToFilename(r.file)
returnr
end
-- Parses the client's request. Returns a dictionary containing pretty much everything
-- the server needs to know about the uri.
returnfunction (request)
locale=request:find("\r\n", 1, true)
ifnotethenreturnnilend
localline=request:sub(1, e-1)
localr= {}
_, i, r.method, r.request=line:find("^([A-Z]+) (.-) HTTP/[1-9]+.[0-9]+$")
r.methodIsValid=validateMethod(r.method)
r.uri=parseUri(r.request)
r.getRequestData=getRequestData(request)
returnr
end