aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRunxi Yu <me@runxiyu.org>2025-03-15 17:16:05 +0800
committerRunxi Yu <me@runxiyu.org>2025-03-15 17:16:05 +0800
commit0b541fefa3fbf8db830a2d4c52f3a33c20bae4c6 (patch)
tree270ce35ab28f0960487c5bdfc9bdd7347dc14222
parentUse abort("unreachable") instead of a random comment (diff)
downloadforge-0b541fefa3fbf8db830a2d4c52f3a33c20bae4c6.tar.gz
forge-0b541fefa3fbf8db830a2d4c52f3a33c20bae4c6.tar.zst
forge-0b541fefa3fbf8db830a2d4c52f3a33c20bae4c6.zip
Serve static files
-rw-r--r--main.ha5
-rw-r--r--req.ha21
2 files changed, 23 insertions, 3 deletions
diff --git a/main.ha b/main.ha
index 58e467b..fc41240 100644
--- a/main.ha
+++ b/main.ha
@@ -2,6 +2,7 @@
// SPDX-FileCopyrightText: Copyright (c) 2025 Runxi Yu <https://runxiyu.org>
// Adapted from template by Willow Barraco <contact@willowbarraco.fr>
+use fs;
use getopt;
use log;
use net;
@@ -21,6 +22,8 @@ const usage: [_]getopt::help = [
('c', "config", "path to configuration file")
];
+let static_fs: nullable *fs::fs = null;
+
export fn main() void = {
const cmd = getopt::parse(os::args, usage...);
defer getopt::finish(&cmd);
@@ -35,6 +38,8 @@ export fn main() void = {
};
};
+ static_fs = os::diropen("static")!;
+
const server = match (http::listen(ip_addr, port, net::tcp::reuseport, net::tcp::reuseaddr)) {
case let this: *http::server =>
yield this;
diff --git a/req.ha b/req.ha
index 3329670..e9fd6fc 100644
--- a/req.ha
+++ b/req.ha
@@ -2,6 +2,7 @@
// SPDX-FileCopyrightText: Copyright (c) 2025 Runxi Yu <https://runxiyu.org>
use fmt;
+use fs;
use htmpl;
use io;
use net::http;
@@ -9,7 +10,7 @@ use net::uri;
use strconv;
use strings;
-fn handlereq(conn: io::handle, request: *http::request) (void | io::error | nomem) = {
+fn handlereq(conn: io::handle, request: *http::request) (void | io::error | nomem | fs::error) = {
let segments = match(segments_from_path(request.target.raw_path)) {
case let s: []str =>
yield s;
@@ -51,6 +52,7 @@ fn handlereq(conn: io::handle, request: *http::request) (void | io::error | nome
fmt::fprintln(conn, "Error: Blank static endpoint")?;
return;
};
+
let fs_segments = segments[2 ..];
for (let fs_segment .. fs_segments) {
if (strings::contains(fs_segment, "/")) {
@@ -59,8 +61,21 @@ fn handlereq(conn: io::handle, request: *http::request) (void | io::error | nome
return;
};
};
- start_response(conn, 501, "text/plain")?;
- fmt::fprintln(conn, "Not implemented yet")?;
+ let fs_segment_path = strings::join("/", fs_segments...)?;
+ defer free(fs_segment_path);
+
+ let file = match (fs::open(static_fs as *fs::fs, fs_segment_path)) {
+ case let f: io::handle => yield f;
+ case fs::error =>
+ start_response(conn, 500, "text/plain")?;
+ fmt::fprintln(conn, "Filesystem error")?;
+ return;
+ };
+ defer io::close(file)!;
+
+ start_response(conn, 200, "text/css")?;
+ io::copy(conn, file)?;
+
case =>
start_response(conn, 404, "text/plain")?;
fmt::fprintln(conn, "Error: Unknown system endpoint")?;