add static file routing

This commit is contained in:
HorizonCode 2023-05-10 14:57:29 +02:00
parent b2c2ff84fe
commit c6c739394f
2 changed files with 52 additions and 7 deletions

View File

@ -4,7 +4,7 @@ import { HTTPServer } from "../http_server.ts";
const httpServer = new HTTPServer(); const httpServer = new HTTPServer();
httpServer.add("GET", "/", (_req, rep) => { httpServer.add("GET", "/", (_req, rep) => {
rep.statusCode = Status.Teapot; rep.statusCode = Status.Teapot;
rep.addHeader("working", "true") rep.addHeader("working", "true");
return JSON.stringify( return JSON.stringify(
{ {
code: Status.Teapot, code: Status.Teapot,
@ -16,4 +16,6 @@ httpServer.add("GET", "/", (_req, rep) => {
}); });
httpServer.listen({ httpServer.listen({
port: 8080, port: 8080,
staticLocalDir: "/static",
staticServePath: "/assets",
}); });

View File

@ -2,10 +2,12 @@ import {
Status, Status,
STATUS_TEXT, STATUS_TEXT,
} from "https://deno.land/std@0.186.0/http/http_status.ts"; } from "https://deno.land/std@0.186.0/http/http_status.ts";
import * as path from "https://deno.land/std@0.185.0/path/mod.ts";
type ListenOptions = { type ListenOptions = {
port: number; port: number;
host?: string; host?: string;
staticLocalDir?: string;
staticServePath?: string;
}; };
type HTTPMethod = "GET" | "POST" | "PUSH" | "DELETE"; type HTTPMethod = "GET" | "POST" | "PUSH" | "DELETE";
type RouteHandler = ( type RouteHandler = (
@ -19,6 +21,8 @@ export class HTTPServer {
private urlRegex = new RegExp(/(http[s]?:\/\/)?([^\/\s]+\/)(.*)/); private urlRegex = new RegExp(/(http[s]?:\/\/)?([^\/\s]+\/)(.*)/);
private server?: Deno.Listener; private server?: Deno.Listener;
private routes = new Map<string, Route>(); private routes = new Map<string, Route>();
private staticLocalDir?: string;
private staticServePath?: string;
async listen(options: ListenOptions) { async listen(options: ListenOptions) {
this.server = Deno.listen({ this.server = Deno.listen({
@ -26,12 +30,51 @@ export class HTTPServer {
hostname: options.host, hostname: options.host,
}); });
if (options.staticLocalDir && options.staticServePath) {
this.staticLocalDir = options.staticLocalDir;
this.staticServePath = options.staticServePath;
}
for await (const conn of this.server) { for await (const conn of this.server) {
const httpConn = Deno.serveHttp(conn); const httpConn = Deno.serveHttp(conn);
for await (const requestEvent of httpConn) { for await (const requestEvent of httpConn) {
const urlPath = this.urlRegex.exec(requestEvent.request.url); const url = new URL(requestEvent.request.url);
const path = urlPath && urlPath.length > 3 ? "/" + urlPath[3] : "/"; const filepath = decodeURIComponent(url.pathname);
const routeName = `${requestEvent.request.method}@${path}`;
if (this.staticServePath && filepath.startsWith(this.staticServePath)) {
console.log(filepath, this.staticServePath);
const fileDir = filepath.split("/").slice(2).join("/");
const pathLoc = path.join(
Deno.cwd(),
this.staticLocalDir as string,
fileDir,
);
console.log(pathLoc);
let file;
try {
file = await Deno.open(pathLoc, { read: true });
} catch {
// If the file cannot be opened, return a "404 Not Found" response
await requestEvent.respondWith(
new Response(
JSON.stringify({
code: 404,
message: `File ${filepath} not found!`,
}),
{
status: Status.NotFound,
},
),
);
continue;
}
const readableStream = file.readable;
const response = new Response(readableStream);
await requestEvent.respondWith(response);
return;
}
const routeName = `${requestEvent.request.method}@${filepath}`;
const route = this.routes.has(routeName) const route = this.routes.has(routeName)
? this.routes.get(routeName) ? this.routes.get(routeName)
: undefined; : undefined;
@ -42,7 +85,7 @@ export class HTTPServer {
requestEvent.request, requestEvent.request,
routeReply, routeReply,
); );
requestEvent.respondWith( await requestEvent.respondWith(
new Response(handler as string, { new Response(handler as string, {
status: routeReply.statusCode, status: routeReply.statusCode,
headers: routeReply.headers, headers: routeReply.headers,
@ -50,7 +93,7 @@ export class HTTPServer {
}), }),
); );
} else { } else {
requestEvent.respondWith( await requestEvent.respondWith(
new Response( new Response(
JSON.stringify({ JSON.stringify({
code: 404, code: 404,