mirror of
https://github.com/CommunitySolidServer/CommunitySolidServer.git
synced 2024-10-03 14:55:10 +00:00

This allows us to decouple the WebSocket listening from the HTTP configs, making these features completely orthogonal.
69 lines
2.5 KiB
TypeScript
69 lines
2.5 KiB
TypeScript
import type { Server, IncomingMessage, ServerResponse } from 'http';
|
|
import { getLoggerFor } from '../logging/LogUtil';
|
|
import { isError } from '../util/errors/ErrorUtil';
|
|
import { guardStream } from '../util/GuardedStream';
|
|
import type { HttpHandler } from './HttpHandler';
|
|
import { ServerConfigurator } from './ServerConfigurator';
|
|
|
|
/**
|
|
* A {@link ServerConfigurator} that attaches an {@link HttpHandler} to the `request` event of a {@link Server}.
|
|
* All incoming requests will be sent to the provided handler.
|
|
* Failsafes are added to make sure a valid response is sent in case something goes wrong.
|
|
*
|
|
* The `showStackTrace` parameter can be used to add stack traces to error outputs.
|
|
*/
|
|
export class HandlerServerConfigurator extends ServerConfigurator {
|
|
protected readonly logger = getLoggerFor(this);
|
|
protected readonly errorLogger = (error: Error): void => {
|
|
this.logger.error(`Request error: ${error.message}`);
|
|
};
|
|
|
|
/** The main HttpHandler */
|
|
private readonly handler: HttpHandler;
|
|
private readonly showStackTrace: boolean;
|
|
|
|
public constructor(handler: HttpHandler, showStackTrace = false) {
|
|
super();
|
|
this.handler = handler;
|
|
this.showStackTrace = showStackTrace;
|
|
}
|
|
|
|
public async handle(server: Server): Promise<void> {
|
|
server.on('request',
|
|
async(request: IncomingMessage, response: ServerResponse): Promise<void> => {
|
|
try {
|
|
this.logger.info(`Received ${request.method} request for ${request.url}`);
|
|
const guardedRequest = guardStream(request);
|
|
guardedRequest.on('error', this.errorLogger);
|
|
await this.handler.handleSafe({ request: guardedRequest, response });
|
|
} catch (error: unknown) {
|
|
const errMsg = this.createErrorMessage(error);
|
|
this.logger.error(errMsg);
|
|
if (response.headersSent) {
|
|
response.end();
|
|
} else {
|
|
response.setHeader('Content-Type', 'text/plain; charset=utf-8');
|
|
response.writeHead(500).end(errMsg);
|
|
}
|
|
} finally {
|
|
if (!response.headersSent) {
|
|
response.writeHead(404).end();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Creates a readable error message based on the error and the `showStackTrace` parameter.
|
|
*/
|
|
private createErrorMessage(error: unknown): string {
|
|
if (!isError(error)) {
|
|
return `Unknown error: ${error}.\n`;
|
|
}
|
|
if (this.showStackTrace && error.stack) {
|
|
return `${error.stack}\n`;
|
|
}
|
|
return `${error.name}: ${error.message}\n`;
|
|
}
|
|
}
|