replace URL with split to gain some extra performance

This commit is contained in:
HorizonCode 2023-05-11 15:59:44 +02:00
parent bbc861fde3
commit 42ae41ba87
2 changed files with 28 additions and 23 deletions

View File

@ -1,16 +1,16 @@
import { Status } from "https://deno.land/std@0.186.0/http/http_status.ts"; import { Status } from "https://deno.land/std@0.186.0/http/http_status.ts";
import { hrtime } from "https://deno.land/std@0.177.0/node/process.ts"; import prettyTime from "npm:pretty-time";
import prettyTime from 'npm:pretty-time';
import { HTTPServer } from "../mod.ts"; import { HTTPServer } from "../mod.ts";
const httpServer = new HTTPServer(); const httpServer = new HTTPServer();
httpServer.middleware(async (req, done) => { httpServer.middleware(async (req, done) => {
const started = hrtime(); const perStart = performance.now();
console.log(`${req.method} - ${req.ip()} - ${req.path}`); console.log(`${req.method} - ${req.ip()} - ${req.path}`);
await done(); await done();
const processTime = hrtime(started); const pt = performance.now() - perStart;
console.log(`Processed in ${prettyTime(processTime)}`); const hrArray: number[] = [0, Math.trunc(pt * 1000000)];
console.log(`Processed in ${prettyTime(hrArray)}`);
}); });
httpServer.error((req, _rep) => { httpServer.error((req, _rep) => {

41
mod.ts
View File

@ -22,8 +22,7 @@ type RouteHandler = (
type RouteMiddlewareHandler = ( type RouteMiddlewareHandler = (
req: RouteRequest, req: RouteRequest,
done: () => Promise<unknown>, done: () => Promise<unknown>,
) => ) => Promise<void>;
| Promise<void>;
type RouteParam = { type RouteParam = {
idx: number; idx: number;
@ -100,14 +99,22 @@ export class HTTPServer {
private async handleHttp(conn: Deno.Conn) { private async handleHttp(conn: Deno.Conn) {
const httpConn = Deno.serveHttp(conn); const httpConn = Deno.serveHttp(conn);
for await (const requestEvent of httpConn) { for await (const requestEvent of httpConn) {
const routeRequest = new RouteRequest(requestEvent.request, conn); const filepath = decodeURIComponent(
"/" + requestEvent.request.url.split("/").slice(3).join("/"),
);
const routeRequest = new RouteRequest(
requestEvent.request,
conn,
filepath,
requestEvent.request.url,
);
const routeReply: RouteReply = new RouteReply(); const routeReply: RouteReply = new RouteReply();
const url = new URL(requestEvent.request.url);
const filepath = decodeURIComponent(url.pathname);
if (filepath.startsWith("/_static")) { if (filepath.startsWith("/_static")) {
this.handleNotFound(routeRequest, routeReply, requestEvent); this.handleNotFound(routeRequest, routeReply, requestEvent);
continue; continue;
} }
let resolveAction: (value?: unknown) => void = () => {}; let resolveAction: (value?: unknown) => void = () => {};
let middlewarePromise; let middlewarePromise;
@ -131,21 +138,20 @@ export class HTTPServer {
try { try {
file = await Deno.open(pathLoc, { read: true }); file = await Deno.open(pathLoc, { read: true });
} catch { } catch {
this.handleNotFound(routeRequest, routeReply, requestEvent);
if (middlewarePromise) resolveAction(); if (middlewarePromise) resolveAction();
this.handleNotFound(routeRequest, routeReply, requestEvent);
continue; continue;
} }
const readableStream = file.readable; const readableStream = file.readable;
const response = new Response(readableStream); const response = new Response(readableStream);
await requestEvent.respondWith(response);
if (middlewarePromise) resolveAction(); if (middlewarePromise) resolveAction();
await requestEvent.respondWith(response);
return; return;
} }
const routeName = `${requestEvent.request.method}@${filepath}`; const routeName = `${requestEvent.request.method}@${filepath}`;
let route = this.routes.has(routeName) let route = this.routes.get(routeName);
? this.routes.get(routeName)
: undefined;
if (route) { if (route) {
let handler = await route.handler( let handler = await route.handler(
@ -157,6 +163,7 @@ export class HTTPServer {
handler = JSON.stringify(handler, null, 2); handler = JSON.stringify(handler, null, 2);
} }
if (middlewarePromise) resolveAction();
await requestEvent.respondWith( await requestEvent.respondWith(
new Response(handler as string, { new Response(handler as string, {
status: routeReply.statusCode, status: routeReply.statusCode,
@ -164,7 +171,6 @@ export class HTTPServer {
statusText: STATUS_TEXT[routeReply.statusCode], statusText: STATUS_TEXT[routeReply.statusCode],
}), }),
); );
if (middlewarePromise) resolveAction();
continue; continue;
} }
@ -189,6 +195,7 @@ export class HTTPServer {
routeRequest, routeRequest,
routeReply, routeReply,
); );
if (middlewarePromise) resolveAction();
await requestEvent.respondWith( await requestEvent.respondWith(
new Response(handler as string, { new Response(handler as string, {
status: routeReply.statusCode, status: routeReply.statusCode,
@ -196,11 +203,10 @@ export class HTTPServer {
statusText: STATUS_TEXT[routeReply.statusCode], statusText: STATUS_TEXT[routeReply.statusCode],
}), }),
); );
if (middlewarePromise) resolveAction();
continue; continue;
} }
this.handleNotFound(routeRequest, routeReply, requestEvent);
if (middlewarePromise) resolveAction(); if (middlewarePromise) resolveAction();
this.handleNotFound(routeRequest, routeReply, requestEvent);
} }
} }
@ -293,14 +299,13 @@ export class RouteRequest {
pathParams: { [key: string]: string }; pathParams: { [key: string]: string };
private remoteIpAddr: string; private remoteIpAddr: string;
constructor(request: Request, conn: Deno.Conn) { constructor(request: Request, conn: Deno.Conn, path: string, url: string) {
this.url = request.url; this.url = url;
const urlObj = new URL(request.url); this.path = decodeURIComponent(path);
this.path = decodeURIComponent(urlObj.pathname);
this.headers = request.headers; this.headers = request.headers;
this.method = request.method as HTTPMethod; this.method = request.method as HTTPMethod;
this.pathParams = {}; this.pathParams = {};
this.queryParams = this.paramsToObject(urlObj.searchParams.entries()); this.queryParams = this.paramsToObject(new URL(url).searchParams.entries());
this.remoteIpAddr = "hostname" in conn.remoteAddr this.remoteIpAddr = "hostname" in conn.remoteAddr
? conn.remoteAddr["hostname"] ? conn.remoteAddr["hostname"]
: "127.0.0.1"; : "127.0.0.1";