From 41eef76c2209c5ef817843d627f871e242490564 Mon Sep 17 00:00:00 2001 From: Jan-Erik Rediger Date: Tue, 28 May 2024 20:28:52 +0200 Subject: [PATCH] some early httpd code --- .gitmodules | 3 ++ backend/cmd/httpd/main.ha | 70 ++++++++++++++++++++++++++++++++++---- backend/vendor/hare-logfmt | 1 + 3 files changed, 68 insertions(+), 6 deletions(-) create mode 160000 backend/vendor/hare-logfmt diff --git a/.gitmodules b/.gitmodules index a1ca048..a469f3d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "backend/vendor/hare-http"] path = backend/vendor/hare-http url = https://git.sr.ht/~sircmpwn/hare-http +[submodule "backend/vendor/hare-logfmt"] + path = backend/vendor/hare-logfmt + url = https://git.sr.ht/~blainsmith/hare-logfmt diff --git a/backend/cmd/httpd/main.ha b/backend/cmd/httpd/main.ha index 7babba4..183caa4 100644 --- a/backend/cmd/httpd/main.ha +++ b/backend/cmd/httpd/main.ha @@ -1,8 +1,10 @@ use getopt; use net; use net::ip; +use net::uri; use net::http; use net::dial; +use net::tcp::{reuseaddr}; use os; use memio; use io; @@ -11,6 +13,8 @@ use bufio; use strings; use thread; use time; +use log::logfmt; +use log; const usage: [_]getopt::help = [ "HTTP server", @@ -18,6 +22,9 @@ const usage: [_]getopt::help = [ ]; export fn main() void = { + let l = logfmt::new(os::stdout); + log::setlogger(&l); + const cmd = getopt::parse(os::args, usage...); defer getopt::finish(&cmd); @@ -39,7 +46,7 @@ export fn main() void = { }; }; - const server = match (http::listen(ip_addr, port)) { + const server = match (http::listen(ip_addr, port, reuseaddr)) { case let this: *http::server => yield this; case net::error => abort("failure while listening"); @@ -53,6 +60,7 @@ export fn main() void = { case net::error => abort("failure while serving"); }; + log::println("method", serv_req.request.method, "uri", uri::string(serv_req.request.target)); let tid = thread::spawn(&handle_req, serv_req)!; thread::detach(tid)!; }; @@ -61,11 +69,27 @@ export fn main() void = { fn handle_req(arg: nullable *opaque) void = { let serv_req = arg: *http::server_request; defer http::serve_finish(serv_req); - fmt::printfln("got a request. serving now.")!; let buf = memio::dynamic(); defer io::close(&buf)!; - handlereq(&buf, &serv_req.request); + + let request = &serv_req.request; + let route = (request.method, request.target.path); + switch (request.method) { + case "GET" => + switch (request.target.path) { + case "/" => handle_index(&buf, &serv_req.request); + case => + handle_notfound(&buf, serv_req); + return; + }; + case "OPTIONS" => + handle_cors(&buf, serv_req); + return; + case => + handle_notfound(&buf, serv_req); + return; + }; http::response_write( serv_req.socket, @@ -75,7 +99,43 @@ fn handle_req(arg: nullable *opaque) void = { )!; }; -export fn handlereq(buf: *io::stream, request: *http::request) void = { +export fn handle_notfound(buf: *io::stream, request: *http::server_request) void = { + fmt::fprintfln(buf, "not found")!; + http::response_write( + request.socket, + http::STATUS_NOT_FOUND, + buf, + ("Content-Type", "text/plain") + )!; +}; + +export fn handle_cors(buf: *io::stream, serv_req: *http::server_request) void = { + let request = serv_req.request; + + if (request.target.path == "/v1/exec") { + http::response_write( + serv_req.socket, + http::STATUS_OK, + void, + ("Content-Length", "0"), + ("access-control-allow-origin", "*"), + ("vary", "origin, access-control-request-method, access-control-request-headers"), + ("access-control-allow-methods", "*"), + ("access-control-allow-headers", "*"), + )!; + + return; + }; + + http::response_write( + serv_req.socket, + http::STATUS_METHOD_NOT_ALLOWED, + void, + ("Content-Length", "0") + )!; +}; + +export fn handle_index(buf: *io::stream, request: *http::request) void = { fmt::fprintfln(buf, "Method: {}", request.method)!; fmt::fprintfln(buf, "Path: {}", request.target.path)!; fmt::fprintfln(buf, "Fragment: {}", request.target.fragment)!; @@ -84,8 +144,6 @@ export fn handlereq(buf: *io::stream, request: *http::request) void = { http::write_header(buf, &request.header)!; fmt::fprintfln(buf, "EOF")!; - time::sleep(5 * time::SECOND); - match (request.body) { case void => void; case let body: io::handle => diff --git a/backend/vendor/hare-logfmt b/backend/vendor/hare-logfmt new file mode 160000 index 0000000..2b4a374 --- /dev/null +++ b/backend/vendor/hare-logfmt @@ -0,0 +1 @@ +Subproject commit 2b4a37459be54c83ac6ac6354cddec3e9fa796bf