luet is a libmicrohttpd wrapper, that uses Lua script for end-point definition. It also allows for basic server-site rendering using template.lua module.
Why? Javascript has no place on the server, Python (Django, Flask) has no place in the web, and that's all I know about the web technologies - I'm not a web-dev. I Love Lua <3
luet depends on pkg-config, lua 5.4, libmicrohttpd, and needs C++23 capable compiler.
To build luet, just run:
make allThis will create a single luet executable. Makefile is very simple, make edits to it, depending on your needs.
Some default parameters can be configured, by creating/editing config.hpp file. This file will be created automatically during first compilation. See config.def.h for available parameters.
./luet [options]options:
-d,--defPATH- path to lua file-p,--portPORT- change port the http daemon runs on-h,--help- display help message
The lua definition file has to include at least a single table named routes, that maps end-points to handler functions. The minimal file looks like this:
routes = {
['/'] = function(_)
return {} -- will return OK 200 empty response
end,
}Handler function takes at least one argument: request, and has to return a table. This table can have the following fields:
body(string) - body of the http response. Defaults to empty string.body_length(integer) - length ofbody. Should be provided, if thebodyis not a null-terminated c-string. Defaults tostrlen(body).code(integer) - http response code. Defaults to 200.headers(table) - a (string=string) key-value table of http headers. Following headers:Content-Length,DateandConnectionare added automatically bylibmicrohttpd, and should NOT be included in handler return table.cookies(table) - a (string=string) key-value table of http cookies to add/update.
The request argument is a table, with the following members:
headers(table) - a (string=string) key-value table of http headers.cookies(table) - a (string=string) key-value table of http cookies.params(table) - a (string=string) key-value table of url query parameters (/url?name1=value1&name2=value2&...)body(string) - the body of http requestbody_size(integer) - length ofbodystringmethod(string) - request http methodurl(string) - request url, not including query parametersversion(string) - request http version
The handler functions can also work with url arguments. These are somewhat primitive, and purely positional, but they are here. Url argument is represented using * character in url segment. This part of the url will be provided as an argument to the handler. Example:
['/hello/*/*'] = function(_, first, second)
return {
body = "Hello, " .. first .. " " .. second .. "!",
headers = {
["Content-Type"] = "text/plain",
},
}
end,Important: when url argument is provided in the route, it CAN'T be empty. The route won't be recognized, and 404 page will be returned. For example, for the above route, GET /hello and GET /hello/firstname will both return the 404 page.
To work with templates from lua, you have to include the template module:
local template = require("template")To render the template into string, use template.render(src, args), if your template is already loaded into string, or template.render_file(path, args), if you want to render template directly from disk.
args is a table passed to the lua context while rendering the template. Its members are accessible directly in the template. Ex. if you run:
template.render_file("template.lt.html", { name = "Hatsune Miku" })You can display name in the template using
My name is <% name %>The template syntax itself is very simple: The expressions go between <% %> and statements go between <? ?>:
Variables and expressions
<a href="page-<%page + 2%>"><% next %></a><body><%= content %></body><ul>
<? for i = 1, 3 do ?>
<li>item #<% i %></li>
<? end ?>
</ul><? if 1 > 2 then ?>
Impossible!
<? else ?>
That's right!
<? end ?>See LICENSE