Add custom server API and runtime limits
This commit is contained in:
@@ -22,3 +22,5 @@ zip_read
|
||||
zip_extract
|
||||
gz_compress
|
||||
gz_uncompress
|
||||
server_start_http
|
||||
server_stop
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
:sig
|
||||
pid_t server_start_http(String key, String socket_fn_or_port, String call_uce_filename, String call_function = "")
|
||||
|
||||
:params
|
||||
key : runtime-wide server key
|
||||
socket_fn_or_port : TCP port number or Unix socket path to listen on
|
||||
call_uce_filename : `.uce` file containing `SERVE_HTTP` handlers
|
||||
call_function : optional named `SERVE_HTTP:name` handler
|
||||
return value : listener process PID, or `0` when it could not be started
|
||||
|
||||
:see
|
||||
>sys
|
||||
server_stop
|
||||
task
|
||||
|
||||
:content
|
||||
Starts or updates a custom HTTP listener backed by a UCE handler file.
|
||||
|
||||
The server key is runtime-wide. Calling `server_start_http()` again with the same key and the same bind target updates the mapped UCE file/function without restarting the listener. If the bind target changes, UCE stops the old listener and starts a replacement.
|
||||
|
||||
`socket_fn_or_port` may be a numeric TCP port such as `"19091"` or a Unix socket path.
|
||||
|
||||
Handler files use `SERVE_HTTP`:
|
||||
|
||||
```uce
|
||||
SERVE_HTTP(Request* req)
|
||||
{
|
||||
req->header["Content-Type"] = "text/plain; charset=utf-8";
|
||||
print("hello from custom HTTP\n");
|
||||
}
|
||||
|
||||
SERVE_HTTP:admin(Request* req)
|
||||
{
|
||||
print("named handler\n");
|
||||
}
|
||||
```
|
||||
|
||||
The custom server dispatcher uses the same nonblocking HTTP listener machinery as the built-in HTTP/WebSocket path, and hands request/response data through the normal `Request` object. Handler code may block in the first implementation; future worker dispatch can be added without changing this API.
|
||||
@@ -0,0 +1,19 @@
|
||||
:sig
|
||||
bool server_stop(String key)
|
||||
|
||||
:params
|
||||
key : runtime-wide server key used with `server_start_http()`
|
||||
return value : `true` when no listener remains or a stop signal was sent
|
||||
|
||||
:see
|
||||
>sys
|
||||
server_start_http
|
||||
|
||||
:content
|
||||
Stops a custom server listener by key and removes its registry config.
|
||||
|
||||
```uce
|
||||
server_stop("site-tests-http");
|
||||
```
|
||||
|
||||
`server_stop()` currently targets custom servers started through `server_start_http()`. The same key model is intended to extend to future `server_start_tcp()` and `server_start_udp()` helpers.
|
||||
@@ -0,0 +1,16 @@
|
||||
SERVE_HTTP(Request* req)
|
||||
{
|
||||
req->header["Content-Type"] = "text/plain; charset=utf-8";
|
||||
print("custom-http-default\n");
|
||||
print("method=", req->params["REQUEST_METHOD"], "\n");
|
||||
print("uri=", req->params["REQUEST_URI"], "\n");
|
||||
print("body=", req->in, "\n");
|
||||
}
|
||||
|
||||
SERVE_HTTP:named(Request* req)
|
||||
{
|
||||
req->header["Content-Type"] = "text/plain; charset=utf-8";
|
||||
print("custom-http-named\n");
|
||||
print("function=", req->params["UCE_SERVE_HTTP_FUNCTION"], "\n");
|
||||
print("query=", req->params["QUERY_STRING"], "\n");
|
||||
}
|
||||
+24
-3
@@ -25,7 +25,7 @@ RENDER(Request& context)
|
||||
failed++;
|
||||
};
|
||||
|
||||
u64 sockfd = socket_connect("localhost", 80);
|
||||
u64 sockfd = socket_connect("127.0.0.1", 80);
|
||||
if(sockfd != 0)
|
||||
{
|
||||
bool write_ok = socket_write(sockfd, "GET /tests/index.uce HTTP/1.0\r\nHost: uce.openfu.com\r\n\r\n");
|
||||
@@ -39,7 +39,28 @@ RENDER(Request& context)
|
||||
}
|
||||
else
|
||||
{
|
||||
mark("socket_connect() / socket_write() / socket_read()", "fail", "socket_connect(localhost, 80) returned 0");
|
||||
mark("socket_connect() / socket_write() / socket_read()", "fail", "socket_connect(127.0.0.1, 80) returned 0");
|
||||
}
|
||||
|
||||
pid_t custom_http_pid = server_start_http("site-tests-http", "19091", "servers/http.uce", "named");
|
||||
usleep(200000);
|
||||
u64 custom_http_sockfd = socket_connect("127.0.0.1", 19091);
|
||||
if(custom_http_sockfd != 0)
|
||||
{
|
||||
bool write_ok = socket_write(custom_http_sockfd, "GET /custom-test?alpha=1 HTTP/1.0\r\nHost: localhost\r\n\r\n");
|
||||
String response = socket_read(custom_http_sockfd, 4096, 2);
|
||||
socket_close(custom_http_sockfd);
|
||||
server_stop("site-tests-http");
|
||||
mark(
|
||||
"server_start_http() / SERVE_HTTP:named",
|
||||
(custom_http_pid != 0 && write_ok && response.find("custom-http-named") != String::npos && response.find("query=alpha=1") != String::npos) ? "pass" : "fail",
|
||||
response.substr(0, response.length() > 260 ? 260 : response.length())
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
server_stop("site-tests-http");
|
||||
mark("server_start_http() / SERVE_HTTP:named", "fail", "socket_connect(127.0.0.1, 19091) returned 0; pid=" + std::to_string(custom_http_pid));
|
||||
}
|
||||
|
||||
u64 memfd = memcache_connect();
|
||||
@@ -60,7 +81,7 @@ RENDER(Request& context)
|
||||
}
|
||||
|
||||
MySQL mysql;
|
||||
mysql.connect("localhost", "root", "");
|
||||
mysql.connect("127.0.0.1", "root", "");
|
||||
String mysql_error_text = trim(mysql.error());
|
||||
if(mysql_error_text != "")
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user