4.4.7 • Published 4 months ago

@superhero/http-server v4.4.7

Weekly downloads
-
License
MIT
Repository
github
Last release
4 months ago

HTTP-Server

An HTTP server module for Node.js that supports both HTTP/1.1 and HTTP/2 protocols, with built-in routing, HTTPS support, and stream support that defaults to server-sent events (SSE). Designed to be robust, flexible and extendible, while easy to work with.

Table of Contents

Installation

Install the package using npm:

npm install @superhero/http-server

Getting Started

The @superhero/http-server module integrates with the @superhero/locator and @superhero/router modules to provide a flexible and modular HTTP server.

To get started, you'll need to set up a Locator instance, register your dispatchers, and then locate the HttpServer module using the locator.

Usage

Basic Example

import HttpServer from '@superhero/http-server';
import Locator    from '@superhero/locator';
import Router     from '@superhero/router';

// Instantiate the service locator
const locator = new Locator();

// Instantiate the router
const router = new Router(locator);

// Instantiate the server
const server = new HttpServer(router);

// Register the route dispatcher service
locator.set('hello-dispatcher', {
  dispatch: (request, session) => {
    session.view.body.message = 'Hello, World!';
  },
});

// Routes
const settings = {
  router: {
    routes: {
      hello: {
        criteria: '/hello',
        dispatcher: 'hello-dispatcher',
      },
    },
  },
};

// Bootstrap and start the server
await server.bootstrap(settings);
await server.listen(3000);

Explanation:

  • Import Statements: We instantiate the required components locator, router and server.
  • Dispatcher Registration: Register a dispatcher called 'hello-dispatcher' in the locator.
  • Server Settings: Define the routes, and possible other server configurations, in the settings object.
  • Bootstrap and Listen: Bootstrap the server with the settings and start listening on port 3000.
  • Ready to serve requests: Request to http://localhost:3000/hello will reply { "message": "Hello, World!" }.

HTTPS Setup with Self-Signed Certificate

import fs       from 'node:fs';
import Locator  from '@superhero/locator';

// Instantiate the service locator
const locator = new Locator();

// Locate the server
const server = await locator.lazyload('@superhero/http-server');

// Register necessary services
locator.set('secure-dispatcher', {
  dispatch: (request, session) => {
    session.view.body = { message: 'Secure Hello, World!' };
  },
});

// Server settings and routes
const serverSettings = {
  server: {
    key: fs.readFileSync('path/to/private.key'),
    cert: fs.readFileSync('path/to/server.cert'),
  },
  router: {
    routes: {
      secure: {
        criteria: '/secure',
        dispatcher: 'secure-dispatcher',
      },
    },
  },
};

await server.bootstrap(serverSettings);
await server.listen(443);

!NOTE Replace 'path/to/private.key' and 'path/to/server.cert' with the actual paths to your SSL key and certificate files.

Altering Response Body, Headers, and Status

locator.set('custom-dispatcher', {
  dispatch: (request, session) => {
    session.view.body = { data: 'Custom Data' };
    session.view.headers['Custom-Header'] = 'CustomValue';
    session.view.status = 201; // HTTP 201 Created
  },
});

// Update the routes in the settings
const settings = {
  router: {
    routes: {
      custom: {
        criteria: '/custom',
        dispatcher: 'custom-dispatcher',
      },
    },
  },
};

// Bootstrap and start the server
await server.bootstrap(settings);
await server.listen(3000);

Handling Aborted Requests

locator.set('abort-dispatcher', {
  dispatch: (request, session) => {
    // Abort the request with a custom error
    const error = new Error('Request Aborted');
    error.code = 'E_REQUEST_ABORTED';
    session.abortion.abort(error);
  },
});

// Update the routes in the settings
const settings = {
  router: {
    routes: {
      abort: {
        criteria: '/abort',
        dispatcher: 'abort-dispatcher',
      },
    },
  },
};

// Bootstrap and start the server
await server.bootstrap(settings);
await server.listen(3000);

!NOTE Will result in a status 500 response { "error": "Request Aborted", "code": "E_REQUEST_ABORTED" }

Streaming Server-Sent Events (SSE)

locator.set('sse-dispatcher', {
  dispatch: (request, session) => {
    // Write events to the stream
    session.view.stream.write({ data: 'First message' });
    session.view.stream.write({ data: 'Second message' });

    // End the stream
    session.view.stream.end();
  },
});

// Update the routes in the settings
const settings = {
  router: {
    routes: {
      sse: {
        criteria: '/sse',
        dispatcher: 'sse-dispatcher',
      },
    },
  },
};

// Bootstrap and start the server
await server.bootstrap(settings);
await server.listen(3000);

!NOTE By default responds with a text/event-stream content type:

data: { "data": "First message" }

data: { "data": "Second message" }

Custom Logging

You can override, or hook into, the default logging method to integrate reactions with your logging requirements.

Turn of logs

server.log.config.mute = true

Learn more

Read the github page for the repository this component depend on for logging: @superhero/log.

API

HttpServer

The main class responsible for handling HTTP requests.

  • Constructor: The server can be instantiated or located via the Locator.

    • Use locator.locate('@superhero/http-server') to get an instance.
  • Methods:

    • async bootstrap(settings): Bootstraps the server with the provided settings.
      • settings: An object containing server and router configurations.
    • async listen(port): Starts the server on the specified port.
      • port: The port number to listen on.
    • async close(): Closes the server and all active sessions.

request

An object used to read

  • Properties:
    • body: The request body (Promise).
    • method: The request HTTP method.
    • headers: The request HTTP headers.
    • url: The requested URL.

session.view

An object used within dispatchers to manipulate the response.

  • Properties:
    • body: The response body to be sent to the client.
    • headers: An object containing response headers.
    • status: HTTP status code of the response.
    • stream: A writable stream for sending SSE data, or to be configured to stream some other type of response to the client.

session.abortion

An AbortController used to trigger and manage dispatch abortion.

  • Methods:
    • abort(error): Aborts the request with the provided error.

Testing

The test suite uses Node.js's built-in testing module.

Running Tests

To run the tests, execute:

npm test

Test Coverage

▶ @superhero/http-server
  ▶ Lifecycle
    ✔ Can instantiate HttpServer (8.609311ms)
    ✔ Can bootstrap server with non-secure settings (2.813603ms)
    ✔ Can be configured by the configuration file (37.159723ms)
    ✔ Listens and closes the server as expected (5.81708ms)
    ✔ Rejects if server is not available to listen error (2.290967ms)
    ✔ Rejects if server is not available to close error (1.058432ms)
  ✔ Lifecycle (59.459503ms)
  
  ▶ Routing and Requests
    ▶ HTTP/1
      ✔ Can dispatch a request aligned to the route map (42.67787ms)
      ✔ Can alter the output body (5.709405ms)
      ✔ Can stream HTML5 standard Server-Sent Events (SSE) (9.72838ms)
      ✔ Can alter the output headers (9.330729ms)
      ✔ Can alter the output status (7.159825ms)
      ✔ Can abort the dispatcher (5.969359ms)
      ✔ Can describe an abortion in detail (7.225311ms)
      ✔ Can manage thrown errors in the dispatcher (10.332202ms)
      ✔ Can not mistakenly access the wrong view property (7.490531ms)
      ✔ Can not mistakenly assign a value to the wrong view property (5.522195ms)
      ✔ Support connection keep-alive header (10.362687ms)
    ✔ HTTP/1 (122.952777ms)

    ▶ HTTP/2
      ✔ Can dispatch a request aligned to the route map (24.833859ms)
      ✔ Can alter the output body (8.516916ms)
      ✔ Can stream HTML5 standard Server-Sent Events (SSE) (10.336142ms)
      ✔ Can alter the output headers (8.209538ms)
      ✔ Can alter the output status (7.35682ms)
      ✔ Can abort the dispatcher (8.554265ms)
      ✔ Can describe an abortion in detail (5.330231ms)
      ✔ Can manage thrown errors in the dispatcher (9.391412ms)
      ✔ Can not mistakenly access the wrong view property (7.222525ms)
      ✔ Can not mistakenly assign a value to the wrong view property (8.57349ms)
    ✔ HTTP/2 (99.758519ms)
  ✔ Routing and Requests (222.916463ms)

  ▶ HTTPS server with self-signed certificate
    ▶ TLSv1.2
      ▶ RSA:2048
        ✔ HTTP1 (10.68221ms)
        ✔ HTTP2 (14.607846ms)
      ✔ RSA:2048 (184.393685ms)

      ▶ RSA:4096
        ✔ HTTP1 (11.166249ms)
        ✔ HTTP2 (14.376707ms)
      ✔ RSA:4096 (239.998059ms)

      ▶ ECDSA:P-256
        ✔ HTTP1 (6.998372ms)
        ✔ HTTP2 (9.255564ms)
      ✔ ECDSA:P-256 (52.737888ms)

      ▶ ECDSA:P-384
        ✔ HTTP1 (8.610887ms)
        ✔ HTTP2 (9.7637ms)
      ✔ ECDSA:P-384 (52.826908ms)

      ▶ ECDSA:P-521
        ✔ HTTP1 (9.391868ms)
        ✔ HTTP2 (13.179682ms)
      ✔ ECDSA:P-521 (62.741409ms)

      ▶ EdDSA:Ed25519
        ✔ HTTP1 (10.110816ms)
        ✔ HTTP2 (9.99596ms)
      ✔ EdDSA:Ed25519 (58.01589ms)

      ▶ EdDSA:Ed448
        ✔ HTTP1 (4.651357ms)
        ✔ HTTP2 (10.031462ms)
      ✔ EdDSA:Ed448 (51.550013ms)
    ✔ TLSv1.2 (703.01496ms)

    ▶ TLSv1.3
      ▶ RSA:2048
        ✔ HTTP1 (6.43647ms)
        ✔ HTTP2 (9.551209ms)
      ✔ RSA:2048 (113.791235ms)

      ▶ RSA:4096
        ✔ HTTP1 (18.396852ms)
        ✔ HTTP2 (22.414178ms)
      ✔ RSA:4096 (819.288505ms)

      ▶ ECDSA:P-256
        ✔ HTTP1 (7.036644ms)
        ✔ HTTP2 (11.842337ms)
      ✔ ECDSA:P-256 (100.196088ms)

      ▶ ECDSA:P-384
        ✔ HTTP1 (8.183114ms)
        ✔ HTTP2 (12.428711ms)
      ✔ ECDSA:P-384 (61.367513ms)

      ▶ ECDSA:P-521
        ✔ HTTP1 (12.446168ms)
        ✔ HTTP2 (15.564381ms)
      ✔ ECDSA:P-521 (68.39823ms)

      ▶ EdDSA:Ed25519
        ✔ HTTP1 (4.44369ms)
        ✔ HTTP2 (11.703458ms)
      ✔ EdDSA:Ed25519 (54.613453ms)

      ▶ EdDSA:Ed448
        ✔ HTTP1 (13.499592ms)
        ✔ HTTP2 (11.474115ms)
      ✔ EdDSA:Ed448 (68.423656ms)
    ✔ TLSv1.3 (1287.220809ms)
  ✔ HTTPS server with self-signed certificate (1990.42993ms)
✔ @superhero/http-server (2273.646154ms)

tests 69
suites 8
pass 69

---------------------------------------------------------------------------------------------------------------------
file                   | line % | branch % | funcs % | uncovered lines
---------------------------------------------------------------------------------------------------------------------
index.js               |  91.75 |    91.18 |   74.07 | 92-94 128-129 135-137 266-269 369-373 389-394 397-402 405-410
index.test.js          | 100.00 |   100.00 |  100.00 | 
middleware             |        |          |         | 
 upstream              |        |          |         | 
  header               |        |          |         | 
   accept.js           |  19.23 |   100.00 |   33.33 | 10-51
   content-type.js     |  20.00 |   100.00 |   50.00 | 9-44
   content-type        |        |          |         | 
    application        |        |          |         | 
     json.js           |  31.03 |   100.00 |    0.00 | 9-28
  method.js            |  23.68 |   100.00 |   50.00 | 9-37
view.js                |  92.98 |    88.89 |   84.21 | 133-138 196-200 238-239 247-253
---------------------------------------------------------------------------------------------------------------------
all files              |  86.57 |    93.96 |   83.82 | 
---------------------------------------------------------------------------------------------------------------------

License

This project is licensed under the MIT License.

Contributing

Feel free to submit issues or pull requests for improvements or additional features.

4.3.9

6 months ago

4.4.5

4 months ago

4.3.6

6 months ago

4.4.4

4 months ago

4.3.5

6 months ago

4.4.7

4 months ago

4.3.8

6 months ago

4.4.6

4 months ago

4.3.7

6 months ago

4.4.1

6 months ago

4.3.2

6 months ago

4.4.0

6 months ago

4.4.3

5 months ago

4.3.4

6 months ago

4.4.2

5 months ago

4.3.3

6 months ago

4.3.1

7 months ago

4.3.0

10 months ago

4.2.7

10 months ago

4.2.6

10 months ago

4.2.5

10 months ago

4.2.4

10 months ago

4.2.3

10 months ago

4.2.2

10 months ago

4.2.1

10 months ago

4.2.0

10 months ago

4.1.0

10 months ago

4.0.2

10 months ago

4.0.1

10 months ago

4.0.0

10 months ago