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
|
-- SPDX-License-Identifier: GPL-3.0-or-later
-- check prerequisites
local has_http = pcall(require, 'kres_modules.http') and pcall(require, 'http.request')
if not has_http then
-- skipping http module test because its not installed
os.exit(77)
else
local path = worker.cwd..'/control/'..worker.pid
same(true, net.listen(path, nil, {kind = 'control'}),
'new control sockets were created so map() can work')
local request = require('http.request')
modules.load('http')
local endpoints = http.configs._builtin.webmgmt.endpoints
-- custom endpoints
endpoints['/test'] = {'text/custom', function () return 'hello' end}
-- setup HTTP module with an additional endpoint
http.config({
tls = false,
endpoints = endpoints,
}, 'webtest')
local bound
for _ = 1,1000 do
bound, _err = pcall(net.listen, '127.0.0.1', math.random(20000, 29999), { kind = 'webtest'})
if bound then
break
end
end
assert(bound, 'unable to bind a port for HTTP module (1000 attempts)')
-- globals for this module
local _, host, port
local function start_server()
local server_fd = next(http.servers)
assert(server_fd)
local server = http.servers[server_fd].server
ok(server ~= nil, 'creates server instance')
_, host, port = server:localname()
ok(host and port, 'binds to an interface')
end
-- helper for returning useful values to test on
local function http_get(uri)
local headers, stream = assert(request.new_from_uri(uri .. '/'):go(16))
local body = assert(stream:get_body_as_string())
return tonumber(headers:get(':status')), body, headers:get('content-type')
end
-- test whether http interface responds and binds
local function test_builtin_pages()
local code, body, mime
local uri = string.format('http://%s:%d', host, port)
-- simple static page
code, body, mime = http_get(uri .. '/')
same(code, 200, 'static page return 200 OK')
ok(#body > 0, 'static page has non-empty body')
same(mime, 'text/html', 'static page has text/html content type')
-- custom endpoint
code, body, mime = http_get(uri .. '/test')
same(code, 200, 'custom page return 200 OK')
same(body, 'hello', 'custom page has non-empty body')
same(mime, 'text/custom', 'custom page has custom content type')
-- non-existent page
code = http_get(uri .. '/badpage')
same(code, 404, 'non-existent page returns 404')
-- /stats endpoint serves metrics
code, body, mime = http_get(uri .. '/stats')
same(code, 200, '/stats page return 200 OK')
ok(#body > 0, '/stats page has non-empty body')
same(mime, 'application/json', '/stats page has correct content type')
-- /metrics serves metrics
code, body, mime = http_get(uri .. '/metrics')
same(code, 200, '/metrics page return 200 OK')
ok(#body > 0, '/metrics page has non-empty body')
same(mime, 'text/plain; version=0.0.4', '/metrics page has correct content type')
-- /metrics serves frequent
code, body, mime = http_get(uri .. '/frequent')
same(code, 200, '/frequent page return 200 OK')
ok(#body > 0, '/frequent page has non-empty body')
same(mime, 'application/json', '/frequent page has correct content type')
-- /metrics serves bogus
code, body, mime = http_get(uri .. '/bogus')
same(code, 200, '/bogus page return 200 OK')
ok(#body > 0, '/bogus page has non-empty body')
same(mime, 'application/json', '/bogus page has correct content type')
-- /trace serves trace log for requests
code, body, mime = http_get(uri .. '/trace/localhost/A')
same(code, 200, '/trace page return 200 OK')
ok(#body > 0, '/trace page has non-empty body')
same(mime, 'text/plain', '/trace page has correct content type')
-- /trace checks variables
code = http_get(uri .. '/trace/localhost/BADTYPE')
same(code, 400, '/trace checks type')
code = http_get(uri .. '/trace/')
same(code, 400, '/trace requires name')
end
-- AF_UNIX tests (very basic ATM)
local function test_unix_socket()
local s_path = os.tmpname()
os.remove(s_path) -- on POSIX .tmpname() (usually) creates a file :-/
ok(net.listen(s_path, nil, { kind = 'webmgmt' }), 'AF_UNIX net.listen() on ' .. s_path)
-- Unfortunately we can't use standard functions for fetching http://
local socket = require("cqueues.socket")
local sock = socket.connect({ path = s_path })
local connection = require('http.h2_connection')
local conn = connection.new(sock, 'client')
local _, err = conn:connect()
os.remove(s_path) -- don't leave garbage around, hopefully not even on errors
same(err, nil, 'AF_UNIX connect(): ' .. (err or 'OK'))
same(conn:ping(), true, 'AF_UNIX http ping')
-- here we might do `conn:new_stream()` and some real queries
same(conn:close(), true, 'AF_UNIX close')
end
-- plan tests
local tests = {
start_server,
test_builtin_pages,
test_unix_socket,
}
return tests
end
|