refactor: Separate middleware from Express.

This commit is contained in:
Ruben Verborgh
2020-11-29 23:24:29 +01:00
parent de079062be
commit 023ff80f48
18 changed files with 227 additions and 54 deletions

View File

@@ -1,5 +1,4 @@
import type { Server } from 'http';
import cors from 'cors';
import type { Express } from 'express';
import express from 'express';
import { getLoggerFor } from '../logging/LogUtil';
@@ -17,28 +16,11 @@ export class ExpressHttpServerFactory implements HttpServerFactory {
}
public startServer(port: number): Server {
const app = express();
this.setup(app);
return app.listen(port);
return this.createApp().listen(port);
}
protected setup(app: Express): void {
// Set up server identification
app.use((request, response, done): void => {
response.setHeader('X-Powered-By', 'Community Solid Server');
done();
});
// Set up Cross-Origin Resource Sharing (CORS)
app.use(cors({
// Based on https://github.com/solid/solid-spec/blob/master/recommendations-server.md#cors---cross-origin-resource-sharing
// By default origin is always '*', this forces it to be the origin header if there is one
origin: (origin, callback): void => callback(null, (origin ?? '*') as any),
methods: [ 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT', 'PATCH', 'DELETE' ],
}));
// Delegate to the main handler
app.use(async(request, response, done): Promise<void> => {
protected createApp(): Express {
return express().use(async(request, response, done): Promise<void> => {
try {
this.logger.info(`Received request for ${request.url}`);
await this.handler.handleSafe({ request: guardStream(request), response });

View File

@@ -0,0 +1,26 @@
import cors from 'cors';
import type { RequestHandler } from 'express';
import { HttpHandler } from '../HttpHandler';
import type { HttpRequest } from '../HttpRequest';
import type { HttpResponse } from '../HttpResponse';
/**
* Handler that sets CORS options on the response.
*/
export class CorsHandler extends HttpHandler {
private readonly corsHandler: RequestHandler;
public constructor() {
super();
this.corsHandler = cors({
origin: (origin, callback): void => callback(null, (origin ?? '*') as any),
methods: [ 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT', 'PATCH', 'DELETE' ],
});
}
public async handle(input: { request: HttpRequest; response: HttpResponse }): Promise<void> {
return new Promise((resolve): void => {
this.corsHandler(input.request as any, input.response as any, (): void => resolve());
});
}
}

View File

@@ -0,0 +1,22 @@
import { HttpHandler } from '../HttpHandler';
import type { HttpResponse } from '../HttpResponse';
/**
* Handler that sets custom headers on the response.
*/
export class HeaderHandler extends HttpHandler {
private readonly headers: Record<string, string>;
public constructor() {
super();
this.headers = {
'x-powered-by': 'Community Solid Server',
};
}
public async handle({ response }: { response: HttpResponse }): Promise<void> {
for (const header of Object.keys(this.headers)) {
response.setHeader(header, this.headers[header]);
}
}
}