1.2.20 • Published 5 years ago

@wwu-restek/rt-api-server v1.2.20

Weekly downloads
-
License
ISC
Repository
bitbucket
Last release
5 years ago

ResTek API Server Framework

This is a Node server framework designed with the needs of ResTek in mind. It allows for cleaner namespacing of routes and structuring servers in a way that's scalable.

Setup

This package isn't available on npm (yet), so we'll need to install it to a project via git+ssh.

npm install @wwu-restek/rt-api-server

Documentation

If you want to look at more detailed documentation, run the following:

cd rt-api-server
npm run build_docs

This will create a directory called docs. Open the index.html file in a web browser for the documentation.

Usage

HTTP Server

To setup a basic HTTP server, do the following:

const { RTServer } = require('@wwu-restek/rt-api-server').Server;
const { Route, RouteContainer } = require('@wwu-restek/rt-api-server').Routing;

const server = new RTServer(5000);
const rc = new RouteContainer('test');

rc.addRoute(new Route('GET', '/hello', (req, res) => {
  res.send('Hello, world!');
}));

server.loadRoutes(rc).start();

This creates a server at http://localhost:5000 with a single endpoint http://localhost:5000/test/hello that returns the text Hello, world!.

Routing

There are many ways to add/remove routes at runtime.

We can add or remove a Route at runtime to a RouteContainer/RouteModule:

const { Route, RouteContainer } = require('@wwu-restek/rt-api-server').Routing;

const rc = new RouteContainer('/');
const route = new Route('GET', 'test', (req, res) => res.send('Hello, world!'));

// Add route
rc.addRoute(route);

// Remove route
rc.removeRoute(route);

In order to remove a route, you MUST save a reference to the route.

We can also add/remove RouteContainers to other RouteContainers or RouteModules:

const childRC = new RouteContainer('child');
const parentRC = new RouteContainer('parent');

// Merge the child RouteContainer
parentRC.addRouteContainer(childRC);

// Remove the child RouteContainer
parentRC.removeRouteContainer(childRC);

Similar to removing Routes, you MUST save a reference to the child RouteContainer in order to remove it.

Route Modules

We can wrap up an entire API server's routing tree and export that as a plugin that other microservices/APIs can use.

const { RouteModule } = require('@wwu-restek/rt-api-server').Routing;
const rc = require('./someRouteContainer'); // This is a RouteContainer object

const rm = new RouteModule('/');
rm.addRouteContainer(rc);

module.exports = rm;

We can now use this RouteModule in other APIs/microservices as a pluggable routing module.

Route modules can also quickly create their own small RTServers that are great for development or testing.

const { Route, RouteModule } = require('@wwu-restek/rt-api-server').Routing;

const route = new Route('GET', '/test', (req, res) => res.send('Hello, world!'));

const rm = new RouteModule('/');
rm.addRoute(route);

rm.start(); // Picks a port that is available for use to serve /test

Authentication

@wwu-restek/rt-api-server comes bundled with configuration options and middleware to make CAS authentication easy to use. It uses the @wwu-restek/simple-cas module to accomplish everything related to CAS.

At the server level

To configure an RTServer object to use CAS globally:

const { RTServer } = require('@wwu-restek/rt-api-server').Server;

const server = new RTServer(80, { 
  session: { /* session configuration */},
  auth: { baseHost: <some base>, serviceUrl: <CAS redirect URL> },
});

auth can be set to a boolean to use the default behavior or can be an object with two optional parameters. The default behavior is to redirect the client to CAS and have them return to the exact same route that they requested originally.

baseHost is an optional paramater for the hostname for CAS to redirect to after authentication. This is useful if you have a server running at localhost:8000 since req.hostname doesn't preserve the port number in the hostname.

serviceUrl is a full URL for CAS to redirect to after authentication. This is optional in case you need users to redirect back to a front-end server after being redirected from the backend.

NOTE - You need to configure sessions in order to use CAS authentication. This is because the server needs somewhere to store CAS authentication information. The middleware that is used will throw an error if there is no session.

As middleware

There is also middleware that can be used just to protect individual routes or route containers:

const { RouteContainer } = require('@wwu-restek/rt-api-server').Routing;
const { auth } = require('@wwu-restek/rt-api-server').Auth;

const rc = new RouteContainer('/', auth({ baseHost: 'some base', serviceUrl: 'some service url' }));

auth takes either true or a configuration object. The behavior is the same as the server config.

Middleware

We can add middleware a couple of different ways.

We can add middleware to an RTServer, RouteContainer, or Route at instantiation:

// Add middleware to all routes of a server
const server = new RTServer(5000, { middleware: [(req, res, next) => { console.log('Hello, world!'); next(); }] });

// Add middleware to all routes within a RouteContainer
const rc = new RouteContainer('test', 
                              (req, res, next) => { console.log("I'm middleware 1"); next(); },
                              (req, res, next) => { console.log("I'm middleware 2"); next(); },
);

// Add middleware to a single route
const route = new Route('GET', 
                        '/foo',
                        (req, res, next) => { console.log("I'm route-specific middleware"); next(); },
                        (req, res) => { res.send('foo'); },
);

We can also add middleware to any of these objects after instantiation:

server.addMiddleware(middleware1, middleware2);
rc.addMiddleware(middleware3);
route.addMiddleware(middleware4, middleware5, middleware6);

Error Handling

At any point, you can throw an RTError to send a client an RFC 7807 compliant error message:

const { RTError } = require('rt-api-server').ErrorHandling;

const route = new Route('GET', '/error', (req, res) => { 
  throw new RTError('This is a test error message',      // Description of error
                    400,                                 // HTTP status code
                    { custom: 'Custom error message' }); // (Optional) More details about error for client
});

Socket.io

We can also utilize socket.io for duplex communication:

// server.js
const server = new RTServer(5000, { socket: true });
server.addSocketListener('connection', () => { console.log('Received connection'); });
server.start();
// client.js
const io = require('socket.io-client');
const client = io('http://localhost');
client.on('connect', () => { console.log('Connected'); };
1.2.20

5 years ago

1.2.19

5 years ago

1.2.18

5 years ago

1.2.17

5 years ago

1.2.16

5 years ago

1.2.15

5 years ago

1.2.14

5 years ago

1.2.13

5 years ago

1.2.12

6 years ago

1.2.11

6 years ago

1.2.10

6 years ago

1.2.9

6 years ago

1.2.8

6 years ago

1.2.7

6 years ago

1.2.6

6 years ago

1.2.5

6 years ago

1.2.4

6 years ago

1.2.3

6 years ago

1.2.2

6 years ago

1.2.1

6 years ago

1.2.0

6 years ago

1.1.7

6 years ago

1.1.6

6 years ago

1.1.5

6 years ago

1.1.4

6 years ago

1.1.3

6 years ago

1.1.2

6 years ago

1.1.1

6 years ago

1.1.0

6 years ago

1.0.1

6 years ago

1.0.0

6 years ago