106 lines
2.3 KiB
TypeScript
106 lines
2.3 KiB
TypeScript
|
|
import fastify, { FastifyInstance } from 'fastify';
|
|
import etags from '@fastify/etag';
|
|
import compress, { FastifyCompressOptions } from '@fastify/compress';
|
|
import formbody from '@fastify/formbody';
|
|
import { pino } from 'pino';
|
|
|
|
export type ServerStatus = 'unstarted' | 'starting' | 'ready' | 'closing' | 'closed';
|
|
|
|
export interface HttpConfig {
|
|
address: string;
|
|
port: number;
|
|
tls: false | {
|
|
key: string;
|
|
cert: string;
|
|
};
|
|
exposed_url?: string;
|
|
etag?: boolean;
|
|
compress?: false | FastifyCompressOptions['encodings'];
|
|
cache_control?: {
|
|
static_assets: string;
|
|
};
|
|
}
|
|
|
|
export interface BaseHttpDependencies {
|
|
logger: pino.Logger;
|
|
}
|
|
|
|
export interface RegisterHttpEndpoint<Deps extends BaseHttpDependencies> {
|
|
(server: FastifyInstance, conf: HttpConfig, deps: Deps): void;
|
|
}
|
|
|
|
export interface ContentParser {
|
|
(server: FastifyInstance, media_types: string[]): void;
|
|
}
|
|
|
|
export interface HttpParams<Deps extends BaseHttpDependencies> {
|
|
content_parsers: Record<string, ContentParser>;
|
|
endpoints: RegisterHttpEndpoint<Deps>[];
|
|
}
|
|
|
|
export function create_http_server<Deps extends BaseHttpDependencies>(conf: HttpConfig, deps: Deps, params: HttpParams<Deps>) {
|
|
const server = fastify({
|
|
logger: deps.logger
|
|
});
|
|
|
|
// Register error handlers
|
|
// todo: register error handlers...
|
|
|
|
// Register endpoints
|
|
for (const endpoint of params.endpoints) {
|
|
endpoint(server, conf, deps);
|
|
}
|
|
|
|
// Register content parsers
|
|
for (const [ media_type, parser ] of Object.entries(params.content_parsers)) {
|
|
parser(server, [ media_type ]);
|
|
}
|
|
|
|
let resolve: () => void;
|
|
let status: ServerStatus = 'unstarted';
|
|
|
|
const ready = new Promise<void>((onResolve) => {
|
|
resolve = onResolve;
|
|
});
|
|
|
|
return {
|
|
server,
|
|
ready,
|
|
get status() {
|
|
return status;
|
|
},
|
|
|
|
//
|
|
async setup_plugins() {
|
|
await Promise.all([
|
|
server.register(formbody),
|
|
conf.etag ? server.register(etags) : null,
|
|
conf.compress ? server.register(compress, { encodings: conf.compress }) : null,
|
|
]);
|
|
},
|
|
|
|
async listen() {
|
|
status = 'starting';
|
|
|
|
try {
|
|
await server.listen({ port: conf.port, host: conf.address });
|
|
}
|
|
|
|
catch (error) {
|
|
server.log.error(error);
|
|
process.exit(1);
|
|
}
|
|
|
|
await server.ready();
|
|
status = 'ready';
|
|
resolve();
|
|
},
|
|
async close() {
|
|
status = 'closing';
|
|
await server.close();
|
|
status = 'closed';
|
|
},
|
|
};
|
|
}
|