Compare commits
10 commits
bc8b67361d
...
5ee654f280
Author | SHA1 | Date | |
---|---|---|---|
5ee654f280 | |||
5d25afc329 | |||
3fc77f009d | |||
ea3f379b1b | |||
c45d0a4658 | |||
b3a399cf7a | |||
9bbece2601 | |||
e1d914a28b | |||
c1ccfa70cf | |||
dd2e98ccd9 |
5 changed files with 43 additions and 22 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.0.4",
|
"version": "0.0.12",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./serverus.ts",
|
".": "./serverus.ts",
|
||||||
|
|
9
handlers/index.ts
Normal file
9
handlers/index.ts
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
import * as markdown from './markdown.ts';
|
||||||
|
import * as static_files from './static.ts';
|
||||||
|
import * as typescript from './typescript.ts';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
markdown,
|
||||||
|
static: static_files,
|
||||||
|
typescript
|
||||||
|
};
|
36
server.ts
36
server.ts
|
@ -4,10 +4,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as colors from '@std/fmt/colors';
|
import * as colors from '@std/fmt/colors';
|
||||||
import * as fs from '@std/fs';
|
|
||||||
import * as path from '@std/path';
|
import * as path from '@std/path';
|
||||||
|
|
||||||
const DEFAULT_HANDLER_DIRECTORIES = [path.resolve(path.join(path.dirname(path.fromFileUrl(import.meta.url)), 'handlers'))];
|
const DEFAULT_HANDLER_DIRECTORIES = [import.meta.resolve('./handlers')];
|
||||||
|
|
||||||
/** A `HANDLER` must take a `Request` and return a `Response` if it can handle it. */
|
/** A `HANDLER` must take a `Request` and return a `Response` if it can handle it. */
|
||||||
type HANDLER = (request: Request) => Promise<Response | null | undefined> | Response | null | undefined;
|
type HANDLER = (request: Request) => Promise<Response | null | undefined> | Response | null | undefined;
|
||||||
|
@ -103,26 +102,35 @@ export class SERVER {
|
||||||
this.controller = new AbortController();
|
this.controller = new AbortController();
|
||||||
const { signal } = this.controller;
|
const { signal } = this.controller;
|
||||||
|
|
||||||
const HANDLERS_DIRECTORIES: string[] =
|
const HANDLERS_DIRECTORIES: string[] = Deno.env.get('SERVERUS_HANDLERS')
|
||||||
Deno.env.get('SERVERUS_HANDLERS')?.split(/[;:]/g)?.filter((dir) => dir.length > 0)?.map((dir) => path.resolve(dir)) ??
|
?.split(/[;]/g)
|
||||||
DEFAULT_HANDLER_DIRECTORIES;
|
?.filter((dir) => dir.length > 0)
|
||||||
|
?.map((dir) => {
|
||||||
|
return dir.includes('://') ? dir : path.resolve(dir);
|
||||||
|
}) ?? DEFAULT_HANDLER_DIRECTORIES;
|
||||||
|
|
||||||
for (const handler_directory of HANDLERS_DIRECTORIES) {
|
for (const handler_directory of HANDLERS_DIRECTORIES) {
|
||||||
const resolved_handler_directory_glob = path.resolve(path.join(handler_directory, '*.ts'));
|
const index_file = path.join(handler_directory, 'index.ts');
|
||||||
for await (const globbed_record of fs.expandGlob(resolved_handler_directory_glob)) {
|
|
||||||
if (!globbed_record.isFile) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const import_path = new URL('file://' + globbed_record.path, import.meta.url).toString();
|
try {
|
||||||
const handler_module: HANDLER_MODULE = await import(import_path);
|
const handlers_index = await import(index_file);
|
||||||
if (typeof handler_module.default !== 'function') {
|
|
||||||
console.warn(`Could not load handler, no default exported function: ${globbed_record.path}`);
|
for (const handler_name of Object.keys(handlers_index.default)) {
|
||||||
|
const handler_module: HANDLER_MODULE = handlers_index.default[handler_name];
|
||||||
|
if (typeof handler_module?.default !== 'function') {
|
||||||
|
console.warn(`Could not load handler "${handler_name}" - no default exported function`);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.handlers.push(handler_module);
|
this.handlers.push(handler_module);
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof Deno.errors.NotFound) {
|
||||||
|
console.warn(`Could not load handler index from: ${index_file}`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.handlers.length === 0) {
|
if (this.handlers.length === 0) {
|
||||||
|
|
|
@ -16,13 +16,12 @@ Deno.test({
|
||||||
const old_handlers: string | undefined = Deno.env.get('SERVERUS_HANDLERS');
|
const old_handlers: string | undefined = Deno.env.get('SERVERUS_HANDLERS');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Deno.chdir('./tests/www');
|
|
||||||
Deno.env.set(
|
Deno.env.set(
|
||||||
'SERVERUS_HANDLERS',
|
'SERVERUS_HANDLERS',
|
||||||
`${path.join(path.dirname(path.resolve(path.fromFileUrl(import.meta.url))), 'handlers')}${
|
`${import.meta.resolve('./handlers')}${old_handlers ? (';' + old_handlers) : ''}`
|
||||||
old_handlers ? (';' + old_handlers) : ''
|
|
||||||
}`
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Deno.chdir('./tests/www');
|
||||||
test_server_info = await get_ephemeral_listen_server();
|
test_server_info = await get_ephemeral_listen_server();
|
||||||
|
|
||||||
const response = await fetch(`http://${test_server_info.hostname}:${test_server_info.port}/echo/hello_world.foo`, {
|
const response = await fetch(`http://${test_server_info.hostname}:${test_server_info.port}/echo/hello_world.foo`, {
|
||||||
|
|
5
tests/handlers/index.ts
Normal file
5
tests/handlers/index.ts
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import * as foo from './foo.ts';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
foo
|
||||||
|
};
|
Loading…
Add table
Add a link
Reference in a new issue