@financial-times/express-web-service
v4.0.0
Published
Create Express middleware to serve /__gtg, /__health, /__about, and /__error endpoints.
Downloads
1,889
Maintainers
Keywords
Readme
FT Express Web Service
Create Express middleware to serve /__gtg
, /__health
, /__about
, and /__error
endpoints.
Usage
Requirements
Running Express Web Service requires Node.js 6.x and npm. You can install with:
npm install @financial-times/express-web-service
You'll also need to be using Express 4+. Express Web Service also supports Restify with a few modifications, see the examples for more information.
API Documentation
Familiarity with Express is assumed in the rest of the API documentation. You'll also need to require the module with:
const expressWebService = require("@financial-times/express-web-service")
expressWebService( [options] )
Create and return a middleware for serving FT webservice endpoints, customisable with an options object.
const app = express()
app.use(
expressWebService({
// options
})
)
// or mount on a sub-path
app.use(
"/example",
expressWebService({
// options
})
)
The following routes are added:
Good to go (/__gtg
)
Conforms to the FT Good to go standard, emitting a 200 OK
response if the application should be considered healthy, and 503 Service Unavailable
if it should not. This is intended to be used to make routing decisions.
Always returns 200 OK
unless a goodToGoTest
option is specified.
Health check (/__health
)
Conforms to the FT Healthcheck standard, returning JSON data summarising the current health status of the application.
Always returns an [{ ok:true }]
healthcheck response (ie a valid healthcheck response with a single ok check) unless the healthCheck
option is specified.
About (/__about
)
Conforms to the (at time of writing, draft) FT About endpoint standard, returning JSON data describing the application, and providing links to all relevant dashboards and support documentation resources.
The information emitted by the about endpoint is populated from the about
option. The _hostname
and appVersion
fields will be populated automatically if not present in the data passed in through the about
option.
Error (/__error
)
This endpoint simply throws a JavaScript error, and makes no attempt to handle it. This is useful for testing the way that your application handles runtime errors in prod, both in terms of reporting them (eg to a logging or aggregation tool) and presenting an appropriate UI to the end user.
Options
The available options are as follows:
manifestPath
: (Optional) Path to the app'spackage.json
file. This will be used to populate theappVersion
anddateDeployed
properties of the/__about
endpoint, if they are not specified explicitlyabout
: (Optional) Object containing standard runbook properties as defined in the ft about endpoint standard, or a Promise that resolves to an object containing these propertiesgoodToGoTest
: (Optional) A function that can be used to indicate the good to go status of the service, the function should return a Promise resolved withtrue
to indicate a positive good to go status, andfalse
to indicate a negative good to go statushealthCheck
: (Optional) A function that can be used to generate structured healthcheck information, the function should return a Promise resolved with an array of healthcheck objectsroutes
: (Optional) An array of routes to install. Possible values arehealth
,gtg
,about
anderror
. Defaults to["health", "gtg", "about"]
Examples
Basic example:
const express = require('express');
const expressWebService = require('@financial-times/express-web-service');
const app = express();
app.use(expressWebService({
manifestPath: `${__dirname}/package.json`,
about: {
"schemaVersion": 1,
"name": "build-service",
"purpose": "Front end build process as a service. Fetches specified Origami components from git, runs Origami build process, and returns the resulting CSS or JS bundle over HTTP.",
"audience": "public",
"primaryUrl": "https://origami-build.ft.com",
"serviceTier": "gold"
}
}));
Example with Good To Go logic and Healthcheck logic:
app.use(expressWebService({
manifestPath: `${__dirname}/package.json`,
about: {
"schemaVersion": 1,
"name": "build-service",
"purpose": "Front end build process as a service. Fetches specified Origami components from git, runs Origami build process, and returns the resulting CSS or JS bundle over HTTP.",
"audience": "public",
"primaryUrl": "https://origami-build.ft.com",
"serviceTier": "gold"
},
goodToGoTest: function() {
return new Promise(function(resolve, reject) {
resolve(isApplicationHappy());
});
},
healthCheck: function() {
// You might have several async checks that you need to perform or
// collect the results from, this is a really simplistic example
return new Promise(function(resolve, reject) {
resolve([
{
name: "Database TCP connectivity",
ok: false,
severity: 2,
businessImpact: "Article pages will not be available",
technicalSummary: "The database is dead",
panicGuide: "Check the health status of the database at host <database host>",
checkOutput: "tcp connect failed after 10 seconds on destination port 3306 - destination unreachable",
lastUpdated: new Date().toISOString()
}
]);
});
}
}));
Example of using with Restify rather than Express:
const expressWebService = require("@financial-times/express-web-service")
const restify = require("restify")
const server = restify.createServer()
// Because Restify doesn't mount middleware for routes that don't exist,
// we have to explicitly define the required routes
server.get(
/^\/__(about|gtg|health)$/,
expressWebService({
// config
})
)
Migration
This migration guide aims to help you migrate between major versions of Express Web Service.
Migrating from v2.x.x to v3.x.x
There are some big changes between versions 2 and 3 of this library. Firstly the module has been renamed from express-ftwebservice
to @financial-times/express-web-service
.
The entire API has been updated to use Express middleware:
const express = require("express")
const expressWebService = require("@financial-times/express-web-service")
const app = express()
const options = {}
// Old
expressWebService(app, options)
// New
app.use(expressWebService(options))
Also the about
option now accepts either an object (matching version 2), or a promise which resolves to an object. This allows you to generate your about information asynchronously:
app.use(
expressWebService({
about: {
name: "My App",
},
})
)
// or
app.use(
expressWebService({
about: new Promise((resolve, reject) => {
// do something async
resolve(retrievedAboutInfo)
}),
})
)
Contributing
This module has a full suite of unit tests, and is verified with ESLint. You can use the following commands to check your code before opening a pull request.
make verify # verify JavaScript code with ESLint
make test # run the unit tests and check coverage
Contact
If you have any questions or comments about this module, or need help using it, please either raise an issue, visit #origami-support or email Origami Support.
Licence
This software is published by the Financial Times under the MIT licence.