# The Cranker Router

[Daniel Flower's crank4j](https://github.com/danielflower/crank4j) is
a reverse proxy which provides implicit discovery behaviour.

This is a server which implements a cranker router.

## Install

To install from npm:

```
npm install cranker-router
```

## Start a router

Start from npm package:

```
cranker-router --help
```

to start, specify a port for the router:

```
cranker-router 8090
```

you can also specify a port for the cranker:

```
cranker-router 8090 20000
```


You can also install globally and run:

```
npm install -g cranker-router
cranker-router 8090 20000
```

## Embedding in JS

There's no default server, so you have to embed it.

Start a cranker on port 8090:

```javascript
const crankerRouter = require("./server.js");

async function start() {
  const routerObject = await crankerRouter(8090);
  return routerObject;
}

start().then();
```

Start a cranker, with the router on any old port, which is really good
for testing:

```javascript
const crankerRouter = require("./server.js");

async function start() {
  const routerObject = await crankerRouter(0);
  const routerPort = routerObject.getListener().address().port;
  console.log("router started on", routerPort);
  return routerObject;
}

start().then();
```

What about if you need to know the port of the cranker websocket?

```javascript
const crankerRouter = require("./server.js");

async function start() {
  const routerObject = await crankerRouter(8090);
  const crankerPort = routerObject.getCrankerListener().address().port;
  console.log("cranker started on", crankerPort);
  return routerObject;
}

start().then();
```

Want information about what has been connected?

```javascript
const crankerRouter = require("./server.js");

async function start() {
  const routerObject = await crankerRouter(0);
  const crankerRoutes = routerObject.getCrankedRoutes();
  console.log("paths routed", crankerRoutes.getCrankedRoutes());
  return routerObject;
}

start().then();
```

Do you want a cranker router with some other routes pre-defined?

```javascript
const crankerRouter = require("./server.js");

async function start() {
  const routerObject = await crankerRouter(0);
  routerObject.get("/cranker/status", function (req, res) {
     res.send("<h1>just a test!</h1>");
  });
  return routerObject;
}

start().then();
```

In this situation a connector connecting with the route
`/cranker/status` won't work because the router object's mapping will
take precedence.

These routes follow the express routing rules, the documentation for
which can be found [here.](https://expressjs.com/en/4x/api.html#app.all)

Lastly, how would you start and stop it?

```javascript
const crankerRouter = require("./server.js");

async function start() {
  const routerObject = await crankerRouter(0);
  return routerObject;
}

start().then(router => router.close(););
```


## Performance trade offs and configuration

If a cranker connector websocket is not available to route an
incomming request then cranker router has to wait for the connector to
establish a socket.

The router option `waitOnCrankerTimeout` specifies the number of
miliseconds it waits. The defaut is 8,000 milliseconds, which is 8 seconds.

If it takes longer than 8 seconds to receive a cranker connector
socket then cranker router returns a 504 to the requesting user agent.

This is an acceptable default in the situation when a connector has
been configured to make 2 websocket connections to the cranker router.

If you need a definitively lower response time, even if that might
result in more 504 error responses, then reduce the
`waitOnCrankerTimeout`, for example, like this:

```javascript
const crankerRouter = require("cranker-router");
async function start() {
  const routerObject = await crankerRouter(0, {
     waitOnCrankerTimeout: 2000
  });
  return routerObject;
}
```

## crankit for developement

I maintain a separate project called `crankit` which is a developer
tool to allow you to start a router and then connect node js projects
to it with a command line.

See [crankit](https://github.com/nicferrier/crankit) for more details.
