Repository navigation
Expand file tree
/
Copy path01_http_json.lua
More file actions
137 lines (120 loc) · 3.35 KB
/
Copy path01_http_json.lua
File metadata and controls
137 lines (120 loc) · 3.35 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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
local lunet = require("lunet")
local socket = require("lunet.socket")
local escape_chars = {
["\\"] = "\\\\",
["\""] = "\\\"",
["\b"] = "\\b",
["\f"] = "\\f",
["\n"] = "\\n",
["\r"] = "\\r",
["\t"] = "\\t",
}
local function escape_string(s)
return s:gsub('[\\"\b\f\n\r\t]', escape_chars):gsub("[%z\1-\31]", function(c)
return string.format("\\u%04x", string.byte(c))
end)
end
local function is_array(t)
if type(t) ~= "table" then return false end
local i = 0
for _ in pairs(t) do
i = i + 1
if t[i] == nil then return false end
end
return true
end
local encode_value
local function encode_table(t)
if is_array(t) then
local parts = {}
for i, v in ipairs(t) do
parts[i] = encode_value(v)
end
return "[" .. table.concat(parts, ",") .. "]"
else
local parts = {}
for k, v in pairs(t) do
if type(k) == "string" then
parts[#parts + 1] = '"' .. escape_string(k) .. '":' .. encode_value(v)
end
end
return "{" .. table.concat(parts, ",") .. "}"
end
end
function encode_value(v)
local t = type(v)
if t == "nil" then
return "null"
elseif t == "boolean" then
return v and "true" or "false"
elseif t == "number" then
if v ~= v then return "null" end
if v == math.huge or v == -math.huge then return "null" end
return tostring(v)
elseif t == "string" then
return '"' .. escape_string(v) .. '"'
elseif t == "table" then
return encode_table(v)
else
return "null"
end
end
local function json_encode(value)
return encode_value(value)
end
local listener = nil
local function parse_request_line(data)
local first_line = data:match("^([^\r\n]+)")
if not first_line then return nil end
local method, path = first_line:match("^(%w+)%s+([^%s]+)")
if not method then return nil end
return method, path
end
local function handle_request(client)
local data, _ = socket.read(client)
if not data then
socket.close(client)
return
end
local method, path = parse_request_line(data)
local response_body = json_encode({
message = "Hello from Lunet!",
request = {
method = method,
path = path,
},
example = {
string = "Hello, World!",
number = 42,
boolean = true,
array = {1, 2, 3},
nested = { key = "value" }
}
})
local response = "HTTP/1.1 200 OK\r\n" ..
"Content-Type: application/json\r\n" ..
"Content-Length: " .. #response_body .. "\r\n\r\n" ..
response_body
socket.write(client, response)
socket.close(client)
end
lunet.spawn(function()
local lerr
listener, lerr = socket.listen("tcp", "127.0.0.1", 18080)
if not listener then
print("Failed to listen: " .. (lerr or "unknown"))
return
end
print("HTTP+JSON example server listening on http://127.0.0.1:18080")
print("Try:")
print(" curl http://127.0.0.1:18080/")
print(" curl http://127.0.0.1:18080/hello")
while true do
local client, _ = socket.accept(listener)
if client then
lunet.spawn(function()
handle_request(client)
end)
end
end
end)