Repository: solid/community-server
Pull request #115 (2020-09-02 14:21:00)

Send server identification
Plus a little fix that popped up because of symmetry.


Patch:
diff --git a/src/server/ExpressHttpServer.ts b/src/server/ExpressHttpServer.ts
index 7c6433d87..e2f64b346 100644
--- a/src/server/ExpressHttpServer.ts
+++ b/src/server/ExpressHttpServer.ts
@@ -1,6 +1,6 @@
 import { Server } from 'http';
 import cors from 'cors';
-import express from 'express';
+import express, { Express } from 'express';
 import { HttpHandler } from './HttpHandler';
 
 export class ExpressHttpServer {
@@ -12,7 +12,18 @@ export class ExpressHttpServer {
 
   public listen(port?: number): Server {
     const app = express();
+    this.setup(app);
+    return app.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
@@ -20,15 +31,17 @@ export class ExpressHttpServer {
       methods: [ 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT', 'PATCH', 'DELETE' ],
     }));
 
-    app.use(async(request, response): Promise<void> => {
+    // Delegate to the main handler
+    app.use(async(request, response, done): Promise<void> => {
       try {
         await this.handler.handleSafe({ request, response });
       } catch (error) {
         const errMsg = `${error.name}: ${error.message}\n${error.stack}`;
         process.stderr.write(errMsg);
         response.status(500).contentType('text/plain').send(errMsg);
+      } finally {
+        done();
       }
     });
-    return app.listen(port);
   }
 }


Test patch:
diff --git a/test/unit/server/ExpressHttpServer.test.ts b/test/unit/server/ExpressHttpServer.test.ts
index ee10f6fa5..a33a50a95 100644
--- a/test/unit/server/ExpressHttpServer.test.ts
+++ b/test/unit/server/ExpressHttpServer.test.ts
@@ -42,6 +42,13 @@ describe('ExpressHttpServer', (): void => {
     server.close();
   });
 
+  it('sends server identification in the X-Powered-By header.', async(): Promise<void> => {
+    const res = await request(server).get('/');
+    expect(res.header).toEqual(expect.objectContaining({
+      'x-powered-by': 'Community Solid Server',
+    }));
+  });
+
   it('returns CORS headers for an OPTIONS request.', async(): Promise<void> => {
     const res = await request(server)
       .options('/')
@@ -77,6 +84,13 @@ describe('ExpressHttpServer', (): void => {
     });
   });
 
+  it('returns a 404 when the handler does not do anything.', async(): Promise<void> => {
+    handler.handle = async(input): Promise<void> => {
+      expect(input).toBeDefined();
+    };
+    await request(server).get('/').expect(404);
+  });
+
   it('catches errors thrown by its handler.', async(): Promise<void> => {
     handler.handle = async(): Promise<void> => {
       throw new Error('dummyError');