struct kr_query *kr_rplan_push(struct kr_rplan *, struct kr_query *, const knot_dname_t *, uint16_t, uint16_t);
int kr_rplan_pop(struct kr_rplan *, struct kr_query *);
struct kr_query *kr_rplan_resolved(struct kr_rplan *);
+struct kr_query *kr_rplan_last(struct kr_rplan *);
int kr_nsrep_set(struct kr_query *, size_t, const struct sockaddr *);
uint32_t kr_rand_uint(uint32_t);
int kr_make_query(struct kr_query *query, knot_pkt_t *pkt);
geoip = 'GeoLite2-City.mmdb' -- Optional, see
-- e.g. https://dev.maxmind.com/geoip/geoip2/geolite2/
-- and install mmdblua library
+ endpoints = {},
}
}
.. code-block:: lua
- http.endpoints['/health'] = {'application/json',
+ local on_health = {'application/json',
function (h, stream)
-- API call, return a JSON table
return {state = 'up', uptime = 0}
-- Finalize the WebSocket
ws:close()
end}
+ -- Load module
+ modules = {
+ http = {
+ endpoints = { ['/health'] = on_health }
+ }
+ }
Then you can query the API endpoint, or tail the WebSocket using curl.
local value = 42
-- Expose the service
- http.endpoints['/service'] = {'application/json',
+ local service = {'application/json',
function (h, stream)
-- Get request method and deal with it properly
local m = h:get(':method')
return 405, 'Cannot do that'
end
end}
+ -- Load the module
+ modules = {
+ http = {
+ endpoints = { ['/service'] = service }
+ }
+ }
In some cases you might need to send back your own headers instead of default provided by HTTP handler,
you can do this, but then you have to return ``false`` to notify handler that it shouldn't try to generate
-- Serve known requests, for methods other than GET
-- the endpoint must be a closure and not a preloaded string
-local function serve(h, stream)
+local function serve(endpoints, h, stream)
local hsend = http_headers.new()
local path = h:get(':path')
- local entry = M.endpoints[path]
+ local entry = endpoints[path]
if not entry then -- Accept top-level path match
- entry = M.endpoints[path:match '^/[^/]*']
+ entry = endpoints[path:match '^/[^/?]*']
end
-- Unpack MIME and data
- local mime, data, err
+ local data, mime, ttl, err
if entry then
- mime, data = unpack(entry)
+ mime = entry[1]
+ data = entry[2]
+ ttl = entry[4]
end
-- Get string data out of service endpoint
if type(data) == 'function' then
- data, err = data(h, stream)
+ local set_mime, set_ttl
+ data, err, set_mime, set_ttl = data(h, stream)
+ -- Override default endpoint mime/TTL
+ if set_mime then mime = set_mime end
+ if set_ttl then ttl = set_ttl end
-- Handler doesn't provide any data
if data == false then return end
if type(data) == 'number' then return tostring(data), err end
hsend:append(':status', '200')
hsend:append('content-type', mime)
hsend:append('content-length', tostring(#data))
- local ttl = entry and entry[4]
if ttl then
hsend:append('cache-control', string.format('max-age=%d', ttl))
end
ws:close()
return
else
- local ok, err, reason = http_util.yieldable_pcall(serve, h, stream)
+ local ok, err, reason = http_util.yieldable_pcall(serve, endpoints, h, stream)
if not ok or err then
if err ~= '404' and verbose() then
log('[http] %s %s: %s (%s)', m, path, err or '500', reason)
error('[http] mmdblua library not found, please remove GeoIP configuration')
end
end
- M.interface(conf.host, conf.port, M.endpoints, conf.cert, conf.key)
+ -- Add endpoints to default endpoints
+ local endpoints = conf.endpoints or {}
+ for k, v in pairs(M.endpoints) do
+ endpoints[k] = v
+ end
+ M.interface(conf.host, conf.port, endpoints, conf.cert, conf.key)
end
return M
http = {
port = 0, -- Select random port
cert = false,
+ endpoints = { ['/test'] = {'text/custom', function () return 'hello' end} },
}
}
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')