feature: sort imports to try to ensure parameter paths are less specific
This commit is contained in:
parent
c92ef0688b
commit
4f68a64a88
4 changed files with 72 additions and 10 deletions
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "@andyburke/serverus",
|
"name": "@andyburke/serverus",
|
||||||
"description": "A flexible HTTP server for mixed content. Throw static files, markdown, Typescript and (hopefully, eventually) more into a directory and serverus can serve it up a bit more like old-school CGI.",
|
"description": "A flexible HTTP server for mixed content. Throw static files, markdown, Typescript and (hopefully, eventually) more into a directory and serverus can serve it up a bit more like old-school CGI.",
|
||||||
"version": "0.3.0",
|
"version": "0.4.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./serverus.ts",
|
".": "./serverus.ts",
|
||||||
|
|
|
@ -53,6 +53,11 @@ export default async function handle_typescript(request: Request): Promise<Respo
|
||||||
|
|
||||||
const root_directory = path.resolve(Deno.cwd());
|
const root_directory = path.resolve(Deno.cwd());
|
||||||
|
|
||||||
|
type import_record = {
|
||||||
|
route_path: string;
|
||||||
|
import_path: string;
|
||||||
|
};
|
||||||
|
const imports: import_record[] = [];
|
||||||
for await (
|
for await (
|
||||||
const entry of walk(root_directory, {
|
const entry of walk(root_directory, {
|
||||||
exts: ['.ts'],
|
exts: ['.ts'],
|
||||||
|
@ -70,19 +75,33 @@ export default async function handle_typescript(request: Request): Promise<Respo
|
||||||
|
|
||||||
const import_path = new URL('file://' + entry.path, import.meta.url).toString();
|
const import_path = new URL('file://' + entry.path, import.meta.url).toString();
|
||||||
|
|
||||||
try {
|
imports.push({
|
||||||
const module: ROUTE_HANDLER = await import(import_path) as ROUTE_HANDLER;
|
route_path,
|
||||||
|
import_path
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const pattern = new URLPattern({ pathname: route_path });
|
// try to sort imports such that they're registered like:
|
||||||
|
// /permissions/test
|
||||||
|
// /echo/hi
|
||||||
|
// /echo/:input
|
||||||
|
//
|
||||||
|
// we want paths with parameters to sort later than paths without
|
||||||
|
const sorted_imports = imports.sort((lhs, rhs) => rhs.route_path.localeCompare(lhs.route_path));
|
||||||
|
for (const import_info of sorted_imports) {
|
||||||
|
try {
|
||||||
|
const module: ROUTE_HANDLER = await import(import_info.import_path) as ROUTE_HANDLER;
|
||||||
|
|
||||||
|
const pattern = new URLPattern({ pathname: import_info.route_path });
|
||||||
|
|
||||||
if (Deno.env.get('SERVERUS_TYPESCRIPT_IMPORT_LOGGING')) {
|
if (Deno.env.get('SERVERUS_TYPESCRIPT_IMPORT_LOGGING')) {
|
||||||
console.log(`imported: ${import_path}`);
|
console.log(`imported: ${import_info.import_path}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
routes.set(pattern, module);
|
routes.set(pattern, module);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Error mounting module ${import_path} at ${route_path}\n\n${error}\n`);
|
console.error(`Error mounting module ${import_info.import_path} at ${import_info.route_path}\n\n${error}\n`);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
35
tests/07_test_route_sorting.test.ts
Normal file
35
tests/07_test_route_sorting.test.ts
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
import * as asserts from '@std/assert';
|
||||||
|
import { EPHEMERAL_SERVER, get_ephemeral_listen_server } from './helpers.ts';
|
||||||
|
|
||||||
|
Deno.test({
|
||||||
|
name: 'test that routes are sorted most to least specific',
|
||||||
|
permissions: {
|
||||||
|
env: true,
|
||||||
|
read: true,
|
||||||
|
write: true,
|
||||||
|
net: true
|
||||||
|
},
|
||||||
|
fn: async () => {
|
||||||
|
let test_server_info: EPHEMERAL_SERVER | null = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
Deno.env.set('SERVERUS_ROOT', './tests/www');
|
||||||
|
test_server_info = await get_ephemeral_listen_server();
|
||||||
|
|
||||||
|
const response = await fetch(`http://${test_server_info.hostname}:${test_server_info.port}/echo/hi`, {
|
||||||
|
method: 'GET'
|
||||||
|
});
|
||||||
|
|
||||||
|
const body = await response.text();
|
||||||
|
|
||||||
|
asserts.assert(response.ok);
|
||||||
|
asserts.assert(body);
|
||||||
|
asserts.assertEquals(body, 'hello');
|
||||||
|
} finally {
|
||||||
|
Deno.env.delete('SERVERUS_ROOT');
|
||||||
|
if (test_server_info) {
|
||||||
|
await test_server_info?.server?.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
8
tests/www/echo/hi/index.ts
Normal file
8
tests/www/echo/hi/index.ts
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
export function GET(_req: Request, _meta: Record<string, any>): Response {
|
||||||
|
return new Response('hello', {
|
||||||
|
status: 200,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'text/plain'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue