docs/api/express.md
---
outline: deep
---
# Express
<Badges>
[![npm version](https://img.shields.io/npm/v/@feathersjs/express.svg?style=flat-square)](https://www.npmjs.com/package/@feathersjs/express)
[![Changelog](https://img.shields.io/badge/changelog-.md-blue.svg?style=flat-square)](https://github.com/feathersjs/feathers/blob/dove/packages/express/CHANGELOG.md)
</Badges>
```
npm install @feathersjs/express --save
```
The `@feathersjs/express` module contains [Express](http://expressjs.com/) framework integrations for Feathers:
- The [Express framework bindings](#expressapp) to make a Feathers application Express compatible
- An Express based transport to expose services through a [REST API](#expressrest)
- An [Express error handler](#expresserrorhandler) for [Feathers errors](./errors.md)
```ts
import { feathers } from '@feathersjs/feathers'
import express from '@feathersjs/express'
const app = express(feathers())
```
<BlockQuote type="warning" label="Important">
As of Feathers v5, [Koa](./koa.md) is the recommended framework integration since it is more modern, faster and easier to use. When chosen explicitly, you should already be familiar with [Express](http://expressjs.com/en/guide/routing.html).
</BlockQuote>
## express(app)
`express(app) -> app` is a function that turns a [Feathers application](./application.md) into a fully Express (4+) compatible application that additionally to Feathers functionality also lets you use the [Express API](http://expressjs.com/en/4x/api.html).
```ts
import { feathers } from '@feathersjs/feathers'
import express from '@feathersjs/express'
const app = express(feathers())
```
Note that `@feathersjs/express` also exposes the Express [built-in middleware](#built-ins)
## express(app, expressApp)
`express(app, expressApp) -> app` allows to extend an existing Express application with the Feathers application `app`.
## express()
If no Feathers application is passed, `express() -> app` returns a plain Express application just like a normal call to Express would.
## app.use(path, service|mw|\[mw\])
`app.use(path, service|mw|[mw]) -> app` registers either a [service object](./services.md), an [Express middleware](http://expressjs.com/en/guide/writing-middleware.html) or an array of [Express middleware](http://expressjs.com/en/guide/writing-middleware.html) on the given path. If [a service object](./services.md) is passed it will use Feathers registration mechanism, for a middleware function Express.
```ts
// Register a service
app.use('todos', {
async get(id) {
return { id }
}
})
// Register an Express middleware
app.use('/test', (req, res) => {
res.json({
message: 'Hello world from Express middleware'
})
})
// Register multiple Express middleware functions
app.use(
'/test',
(req, res, next) => {
res.data = 'Step 1 worked'
next()
},
(req, res) => {
res.json({
message: `Hello world from Express middleware ${res.data}`
})
}
)
```
## app.listen(port)
`app.listen(port) -> Promise<HttpServer>` will first call Express [app.listen](http://expressjs.com/en/4x/api.html#app.listen) and then internally also call the [app.setup(server)](./application.md#setup-server).
```ts
// Listen on port 3030
const server = await app.listen(3030)
```
## app.setup(server)
`app.setup(server) -> app` is usually called internally by `app.listen` but in the cases described below needs to be called explicitly.
### Sub-Apps
When registering an application as a sub-app, `app.setup(server)` has to be called to initialize the sub-apps services.
```ts
import { feathers } from '@feathersjs/feathers'
import express from '@feathersjs/express'
const api = feathers()
api.use('service', myService)
const mainApp = express(feathers()).use('/api/v1', api)
const server = await mainApp.listen(3030)
// Now call setup on the Feathers app with the server
await api.setup(server)
```
### HTTPS
HTTPS requires creating a separate server in which case `app.setup(server)` also has to be called explicitly. In a generated application `src/index.js` should look like this:
```ts
import https from 'https'
import { app } from './app'
const port = app.get('port')
const server = https
.createServer(
{
key: fs.readFileSync('privatekey.pem'),
cert: fs.readFileSync('certificate.pem')
},
app
)
.listen(443)
// Call app.setup to initialize all services and SocketIO
app.setup(server)
server.on('listening', () => logger.info('Feathers application started'))
```
### Virtual Hosts
The [vhost](https://github.com/expressjs/vhost) Express middleware can be used to run a Feathers application on a virtual host but again requires `app.setup(server)` to be called explicitly.
```ts
import vhost from 'vhost'
import { feathers } from '@feathersjs/feathers'
import express from '@feathersjs/express'
const app = express(feathers())
app.use('/todos', todoService)
const host = express().use(vhost('foo.com', app))
const server = await host.listen(8080)
// Here we need to call app.setup because .listen on our virtual hosted
// app is never called
app.setup(server)
```
## rest()
Registers a Feathers transport mechanism that allows you to expose and consume [services](./services.md) through a [RESTful API](https://en.wikipedia.org/wiki/Representational_state_transfer). This means that you can call a service method through the `GET`, `POST`, `PUT`, `PATCH` and `DELETE` [HTTP methods](https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol):
| Service method | HTTP method | Path |
| -------------- | ----------- | ----------- |
| .find() | GET | /messages |
| .get() | GET | /messages/1 |
| .create() | POST | /messages |
| .update() | PUT | /messages/1 |
| .patch() | PATCH | /messages/1 |
| .remove() | DELETE | /messages/1 |
### app.configure(rest())
Configures the transport provider with a standard formatter sending JSON response via [res.json](http://expressjs.com/en/4x/api.html#res.json).
```ts
import { feathers } from '@feathersjs/feathers'
import express, { json, urlencoded, rest } from '@feathersjs/express'
// Create an Express compatible Feathers application
const app = express(feathers())
// Turn on JSON parser for REST services
app.use(json())
// Turn on URL-encoded parser for REST services
app.use(urlencoded({ extended: true }))
// Set up REST transport
app.configure(rest())
```
<BlockQuote type="danger" label="Important">
The `json` and `urlencoded` body parser and [params middleware](#params) has to be registered **before** any service.
</BlockQuote>
### app.configure(rest(formatter))
The default REST response formatter is a middleware that formats the data retrieved by the service as JSON. If you would like to configure your own `formatter` middleware pass a `formatter(req, res)` function. This middleware will have access to `res.data` which is the data returned by the service. [res.format](http://expressjs.com/en/4x/api.html#res.format) can be used for content negotiation.
```ts
import { feathers } from '@feathersjs/feathers'
import express, { json, urlencoded, rest } from '@feathersjs/express'
const app = express(feathers())
// Turn on JSON parser for REST services
app.use(json())
// Turn on URL-encoded parser for REST services
app.use(urlencoded({ extended: true }))
// Set up REST transport
app.configure(
rest(function (req, res) {
// Format the message as text/plain
res.format({
'text/plain': function () {
res.end(`The Message is: "${res.data.text}"`)
}
})
})
)
```
## Custom service middleware
Custom Express middleware that only should run before or after a specific service can be passed to `app.use` in the order it should run:
```ts
const todoService = {
async get(id: Id) {
return {
id,
description: `You have to do ${id}!`
}
}
}
app.use('todos', logRequest, todoService, updateData)
```
<BlockQuote type="danger">
Custom middleware will only run for REST requests and not when used with other transports (like Socket.io). If possible try to avoid custom middleware and use [hooks](hooks.md) or customized services instead which will work for all transports.
</BlockQuote>
Middleware that runs after the service has the service call information available as
- `res.data` - The data that will be sent
- `res.hook` - The [hook](./hooks.md) context of the service method call
For example `updateData` could look like this:
```js
function updateData(req, res, next) {
res.data.updateData = true
next()
}
```
If you run `res.send` in a custom middleware after the service and don't call `next`, other middleware (like the REST formatter) will be skipped. This can be used to e.g. render different views for certain service method calls, for example to export a file as CSV:
```ts
import json2csv from 'json2csv'
const fields = ['done', 'description']
app.use('todos', todoService, function (req, res) {
const result = res.data
const data = result.data // will be either `result` as an array or `data` if it is paginated
const csv = json2csv({ data, fields })
res.type('csv')
res.end(csv)
})
```
## params
All Express middleware will have access to the `req.feathers` object to set properties on the service method `params`:
```ts
import { feathers } from '@feathersjs/feathers'
import type { Id, Params } from '@feathersjs/feathers'
import express, { json, urlencoded, rest } from '@feathersjs/express'
const app = express(feathers())
app.use(json())
app.use(urlencoded({ extended: true }))
app.use(function (req, res, next) {
req.feathers.fromMiddleware = 'Hello world'
next()
})
app.configure(rest())
app.use('todos', {
async get(id: Id, params: Params) {
console.log(params.provider) // -> 'rest'
console.log(params.fromMiddleware) // -> 'Hello world'
return {
id,
params,
description: `You have to do ${id}!`
}
}
})
app.listen(3030)
```
Avoid setting `req.feathers = something` directly since it may already contain information that other Feathers plugins rely on. Adding individual properties or using `{ ...req.feathers, something }` is the more reliable option.
<BlockQuote type="warning" label="Important">
Since the order of Express middleware matters, any middleware that sets service parameters has to be registered **before** `app.configure(rest())` or as a [custom service middleware](#custom-service-middleware)
</BlockQuote>
<BlockQuote type="tip">
Although it may be convenient to set `req.feathers.req = req` to have access to the request object in the service, we recommend keeping your services as provider independent as possible. There usually is a way to pre-process your data in a middleware so that the service does not need to know about the HTTP request or response.
</BlockQuote>
### params.query
`params.query` will contain the URL query parameters sent from the client. For the REST transport the query string is parsed using the [qs](https://github.com/ljharb/qs) module. For some query string examples see the [database querying](./databases/querying.md) chapter.
<BlockQuote type="warning">
Only `params.query` is passed between the server and the client, other parts of `params` are not. This is for security reasons so that a client can't set things like `params.user` or the database options. You can always map from `params.query` to other `params` properties in a [hook](./hooks.md).
</BlockQuote>
For example:
```
GET /messages?read=true&$sort[createdAt]=-1
```
Will set `params.query` to
```json
{
"read": "true",
"$sort": { "createdAt": "-1" }
}
```
<BlockQuote type="tip">
Note that the URL is a string so type conversion may be necessary. This is usually done with [query schemas and resolvers](./schema/index.md).
</BlockQuote>
<BlockQuote type="danger">
If an array in your request consists of more than 20 items, the [qs](https://www.npmjs.com/package/qs) parser implicitly [converts](https://github.com/ljharb/qs#parsing-arrays) it to an object with indices as keys. To extend this limit, you can set a custom query parser: `app.set('query parser', str => qs.parse(str, {arrayLimit: 1000}))`
</BlockQuote>
### params.provider
For any [service method call](./services.md) made through REST `params.provider` will be set to `rest`. In a [hook](./hooks.md) this can for example be used to prevent external users from making a service method call:
```ts
import { HookContext } from 'declarations'
app.service('users').hooks({
before: {
remove: [
async (context: HookContext) => {
// check for if(context.params.provider) to prevent any external call
if (context.params.provider === 'rest') {
throw new Error('You can not delete a user via REST')
}
}
]
}
})
```
### params.headers
`params.headers` will contain the original service request headers.
### params.route
Express route placeholders in a service URL will be added to the services `params.route`. See the [FAQ entry on nested routes](../help/faq.md#how-do-i-do-nested-or-custom-routes) for more details on when and when not to use nested routes.
```ts
import { feathers } from '@feathersjs/feathers'
import express, { rest } from '@feathersjs/express'
const app = express(feathers())
app.configure(rest())
app.use(function (req, res, next) {
req.feathers.fromMiddleware = 'Hello world'
next()
})
app.use('users/:userId/messages', {
async get(id, params) {
console.log(params.query) // -> ?query
console.log(params.provider) // -> 'rest'
console.log(params.fromMiddleware) // -> 'Hello world'
console.log(params.route.userId) // will be `1` for GET /users/1/messages
return {
id,
params,
read: false,
text: `Feathers is great!`,
createdAt: new Date().getTime()
}
}
})
app.listen(3030)
```
## Middleware
`@feathersjs/express` comes with the following middleware
### notFound(options)
`notFound()` returns middleware that returns a `NotFound` (404) [Feathers error](./errors.md). It should be used as the last middleware **before** the error handler. The following options are available:
- `verbose`: Set to `true` if the URL should be included in the error message (default: `false`)
```ts
import { notFound, errorHandler } from '@feathersjs/express'
// Return errors that include the URL
app.use(notFound({ verbose: true }))
app.use(errorHandler())
```
### errorHandler()
`errorHandler` is an [Express error handler](https://expressjs.com/en/guide/error-handling.html) middleware that formats any error response to a REST call as JSON (or HTML if e.g. someone hits our API directly in the browser) and sets the appropriate error code.
<BlockQuote type="tip">
You can still use any other Express compatible [error middleware](http://expressjs.com/en/guide/error-handling.html) with Feathers.
</BlockQuote>
<BlockQuote type="danger" label="Important">
Just like in Express, the error handler has to be registered _after_ all middleware and services.
</BlockQuote>
#### app.use(errorHandler())
Set up the error handler with the default configuration.
```ts
import { feathers } from '@feathersjs/feathers'
import express from '@feathersjs/express'
const app = express(feathers())
// before starting the app
app.use(express.errorHandler())
```
#### app.use(errorHandler(options))
```ts
import { feathers } from '@feathersjs/feathers'
import express from '@feathersjs/express'
const app = express(feathers())
// Just like Express your error middleware needs to be
// set up last in your middleware chain.
app.use(
express.errorHandler({
html: function (error, req, res, next) {
// render your error view with the error object
res.render('error', error)
}
})
)
app.use(
errorHandler({
html: {
404: 'path/to/notFound.html',
500: 'there/will/be/robots.html'
}
})
)
```
<BlockQuote type="warning" label="important">
If you want to have the response in json format be sure to set the `Accept` header in your request to `application/json` otherwise the default error handler will return HTML.
</BlockQuote>
The following options can be passed when creating a new error handler:
- `html` (Function|Object) [optional] - A custom formatter function or an object that contains the path to your custom html error pages. Can also be set to `false` to disable html error pages altogether so that only JSON is returned.
- `logger` (Function|false) (default: `console`) - Set a logger object to log the error (it will be logger with `logger.error(error)`
### authenticate()
`express.authenticate(...strategies)` allows to protect an Express middleware with an [authentication service](./authentication/service.md) that has [strategies](./authentication/strategy.md) registered that can parse HTTP headers. It will set the authentication information on the `req` object (e.g. `req.user`). The following example protects the `/hello` endpoint with the JWT strategy (so the `Authorization: Bearer <JWT>` header needs to be set) and uses the user email to render the message:
```ts
import { authenticate } from '@feathersjs/express'
app.use('/hello', authenticate('jwt'), (req, res) => {
const { user } = req.feathers
res.render(`Hello ${user.email}`)
})
// When using with the non-default authentication service
app.use(
'/hello',
authenticate({
service: 'v2/auth',
strategies: ['jwt', 'api-key']
}),
(req, res) => {
const { user } = req.feathers
res.render(`Hello ${user.email}`)
}
)
```
When clicking a normal link, web browsers do _not_ send the appropriate header. In order to initate an authenticated request to a middleware from a browser link, there are two options. One is using a session which is described in the [Server Side rendering guide](../cookbook/express/view-engine.md), another is to add the JWT access token to the query string and mapping it to an authentication request:
```ts
import { authenticate } from '@feathersjs/express'
const setQueryAuthentication = (req, res, next) => {
const { access_token } = req.query
if (access_token) {
req.authentication = {
strategy: 'jwt',
accessToken: access_token
}
}
next()
}
// Request this with `hello?access_token=<your jwt>`
app.use('/hello', setQueryAuthentication, authenticate('jwt'), (req, res) => {
const { user } = req.feathers
res.render(`Hello ${user.email}`)
})
```
How to get the access token from the authentication client is described in the [authentication client documentation](../api/authentication/client.md#app-get-authentication).
<BlockQuote type="warning">
When using HTTPS URLs are safely encrypted but when using this method you have to make sure that access tokens are not logged through any of your logging mechanisms.
</BlockQuote>
### parseAuthentication
The `parseAuthentication` middleware is registered automatically and will use the strategies of the default [authentication service](./authentication/service.md) to parse headers for authentication information. If you want to additionally parse authentication with a different authentication service this middleware can be registered again with that service configured.
```ts
import { parseAuthentication } from '@feathersjs/express'
app.use(
parseAuthentication({
service: 'api/v1/authentication',
strategies: ['jwt', 'local']
})
)
```
### cors
A reference to the [cors](https://github.com/expressjs/cors) module.
### compression
A reference to the [compression](https://github.com/expressjs/compression) module.
### Built ins
Note that `@feathersjs/express` also exposes the standard [Express middleware](http://expressjs.com/en/4x/api.html#express):
- `json` - A JSON body parser
- `urlencoded` - A URL encoded form body parser
- `serveStatic` - To statically host files in a folder
- `Router` - Creates an Express router object