Origami Frontend Components & Services

Readme: origami-service

Provides an extended Express, as well as useful tools for building consistent Origami services.

NPM version
MIT licensed

Table Of Contents

Usage

Requirements

Running the Origami Service module requires Node.js 10.x and npm. You can install with:

npm install @financial-times/origami-service

API Documentation

This library makes use of promises, and provides a wrapper around Express – familiarity is assumed in the rest of the API documentation. You'll also need to require the module with:

const origamiService = require("@financial-times/origami-service")

origamiService( [options] )

This function returns a new Express application preconfigured to run as an Origami service. You can configure the created service with an options object if you need to override any defaults.

const app = origamiService({
    port: 1234,
})

The application's listen function has a different signature to Express, it's wrapped in a promise and uses the port option from the constructor:

const app = origamiService({
    port: 1234,
})
app.listen() // runs on port 1234 and returns a promise

The Express application will have some additional properties, added by the Origami Service module. These will also be added to app.locals so they're available in your views.

The following Express settings will be set:

Handlebars will be used as a view engine with the extension .html. We use Express Handlebars for this, which means layouts and partials are supported. Add layouts and partials to views/layouts and views/partials respectively. See the examples for more information.

Some middleware will also be mounted by default, in this order:

Options

The Origami Service module can be configured with a variety of options, passed in as an object to the origamiService function or as environment variables. The priority given to each type of configuration is important:

  1. Options object: options passed in as an options object will take priority over everything. E.g. this means if you hard-code the port configuration in your code, the PORT environment variable will cease to work.
  2. Environment: if an option isn't found in the options object, then for some options an environment variable will be checked. The names of these are slightly different, and will be documented below.
  3. Defaults: if an option isn't found in the options object or environment, then it will use the default value as documented below.

The available options are as follows. Where two names are separated by a /, the first is the object key and the second is the environment variable:

origamiService.middleware.notFound( [message] )

Create and return a middleware for throwing 404 "Not Found" errors. The returned middleware will pass on an error which can be caught later by an error handling middleware. The error will have a status property set to 404 so that your error handler can differentiate it from other errors, as well as a cacheMaxAge property set to '30s'.

This middleware should be mounted after all of your application routes:

// routes go here
app.use(origamiService.middleware.notFound())
// error handler goes here

By default, the error message will be set to 'Not Found'. If you wish to specify a custom message you can specify one as a parameter:

app.use(origamiService.middleware.notFound("This page does not exist"))

origamiService.middleware.errorHandler()

Create and return a middleware for rendering errors that occur in the application routes. The returned middleware logs errors to Sentry (if the sentryDsn option is present) and then renders an error page.

The following properties can be set on an error object to change the behaviour of the error handler:

This middleware should be mounted after all of your application routes, and is useful in conjunction with origamiService.middleware.notFound:

// routes go here
app.use(origamiService.middleware.notFound())
app.use(origamiService.middleware.errorHandler())

The error handling middleware will look for a Handlebars template in views/error.html and use it to render the page. If no template is found in that location then it falls back to basic HTML output. This allows you to style your error pages and use your application's default layout.

origamiService.middleware.getBasePath()

Calculate the base path that the application is running on and provide it for use in later middleware and templates. This middleware reads and normalises the FT-Origami-Service-Base-Path header (which should be set by the CDN) and adds it to:

app.use(origamiService.middleware.getBasePath())
// routes go here

origamiService.middleware.cacheControl( options )

Add a Cache-Control header to the response, including stale-if-error and stale-while-revalidate directives. The available options are:

This middleware is best used per-route, rather than at the application level:

app.get(
    "/docs",
    origamiService.middleware.cacheControl({maxAge: "1 day"}),
    () => {
        // route stuff
    }
)

origamiService.middleware.purgeUrls( options )

Create a purge route which will purge all of the given URLs in Fastly when the endpoint is POSTed to. This endpoint accepts general options as well as per-request options in the querystring.

The general options are:

When a user requests the created endpoint, they can use query string parameters to change behaviour:

This middleware should be mounted as a route, rather than at the application level:

app.post(
    "/purge",
    origamiService.middleware.purgeUrls({
        urls: ["https://example.com/url-1", "https://example.com/url-2"],
    })
)

Examples

You can find example implementations of Origami-compliant services in the examples folder of this repo:

  node examples/basic
  node examples/options
  node examples/middleware
  node examples/views

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

Publishing

New versions of the module are published automatically by CI when a new tag is created matching the pattern /v.*/.

Support and Migration

Origami Service major versions are normally supported for 3–6 months after their last minor release. This means that patch-level changes will be added and bugs will be fixed. The table below outlines the end-of-support dates for major versions, and the last minor release for that version.

We also maintain a migration guide to help you migrate.

Major Version Last Minor Release Node.js Versions Support End Date
❤️ 5 N/A 10+ N/A
⌛️ 4 4.1 8+ 2020-12-06
💀 3 3.0 8 2019-03-27
💀 2 2.5 6-8 2018-08-27
💀 1 1.6 6 2017-05-15

If you're opening issues related to these, please mention the version that the issue relates to.

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.

Status
active Origami v1 (Bower)
Switch component view

GitHub: origami-service