REST
$ npm install feathers-rest --save
The feathers-rest module allows you to expose and consume services through a RESTful API. This means that you can call a service method through the GET, POST, PUT, PATCH and DELETE HTTP methods:
| 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 |
Server
To expose services through a RESTful API we will have to configure the feathers-rest plugin and provide our own body parser middleware (usually the standard Express 4 body-parser) to make REST .create, .update and .patch calls parse the data in the HTTP body. If you would like to add other middleware before the REST handler, call app.use(middleware) before registering any services.
$ npm install body-parser --save
Important: For additional information about middleware, routing and how the REST module works with Express middleware see the Express chapter.
ProTip: The body-parser middleware has to be registered before any service. Otherwise the service method will throw a
No data providedorFirst parameter for 'create' must be an objecterror.
app.configure(rest())
Configures the transport provider with a standard formatter sending JSON response via res.json.
const feathers = require('feathers');
const bodyParser = require('body-parser');
const rest = require('feathers-rest');
const app = feathers();
// Turn on JSON parser for REST services
app.use(bodyParser.json())
// Turn on URL-encoded parser for REST services
app.use(bodyParser.urlencoded({ extended: true }));
// Set up REST transport
app.configure(rest())
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 can be used for content negotiation.
const app = feathers();
const bodyParser = require('body-parser');
const rest = require('feathers-rest');
// Turn on JSON parser for REST services
app.use(bodyParser.json())
// Turn on URL-encoded parser for REST services
app.use(bodyParser.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}"`);
}
});
}))
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 module. For some query string examples see the database querying chapter.
Important: Only
params.queryis passed between the server and the client, other parts ofparamsare not. This is for security reasons so that a client can't set things likeparams.useror the database options. You can always map fromparams.queryto otherparamsproperties in a before hook.
params.provider
For any service method call made through REST params.provider will be set to rest. In a hook this can for example be used to prevent external users from making a service method call:
app.service('users').hooks({
before: {
remove(hook) {
// check for if(hook.params.provider) to prevent any external call
if(hook.params.provider === 'rest') {
throw new Error('You can not delete a user via REST');
}
}
}
});
Client
The client module in feathers-rest (require('feathers-rest/client')) allows to connect to a service exposed through the REST server using jQuery, request, Superagent, Axios or Fetch as the AJAX library.
Very important: The examples below assume you are using Feathers either in Node or in the browser with a module loader like Webpack or Browserify. For using Feathers with a
<script>tag, AMD modules or with React Native see the client chapter.
ProTip: REST client services do emit
created,updated,patchedandremovedevents but only locally for their own instance. Real-time events from other clients can only be received by using a websocket connection.
Note: A client application can only use a single transport (either REST, Socket.io or Primus). Using two transports in the same client application is normally not necessary.
rest([baseUrl])
REST client services can be initialized by loading feathers-rest/client and initializing a client object with a base URL:
const feathers = require('feathers/client');
const rest = require('feathers-rest/client');
// Connect to REST endpoints
const restClient = rest();
// Connect to a different URL
const restClient = rest('http://feathers-api.com');
ProTip: The base URL is relative from where services are registered. That means that a service at
http://api.feathersjs.com/api/v1/messageswith a base URL ofhttp://api.feathersjs.comwould be available asapp.service('api/v1/messages'). With a base URL ofhttp://api.feathersjs.com/api/v1it would beapp.service('messages').
REST client wrappers are always initialized using a base URL:
app.configure(restClient.superagent(superagent [, options]));
Default headers can be set for all libaries (except request which has its own defaults mechanism) in the options like this:
app.configure(restClient.superagent(superagent, {
headers: { 'X-Requested-With': 'FeathersJS' }
}));
Then services that automatically connect to that remote URL can be retrieved as usual via app.service:
app.service('messages').create({
text: 'A message from a REST client'
});
Request specific headers can be through params.headers in a service call:
app.service('messages').create({
text: 'A message from a REST client'
}, {
headers: { 'X-Requested-With': 'FeathersJS' }
});
The supported AJAX libraries can be initialized as follows.
jQuery
Pass the instance of jQuery ($) to restClient.jquery:
app.configure(restClient.jquery(window.jQuery));
Or with a module loader:
import $ from 'jquery';
app.configure(restClient.jquery($));
Request
The request object needs to be passed explicitly to feathers.request. Using request.defaults - which creates a new request object - is a great way to set things like default headers or authentication information:
const request = require('request');
const client = request.defaults({
'auth': {
'user': 'username',
'pass': 'password',
'sendImmediately': false
}
});
app.configure(restClient.request(client));
Superagent
Superagent currently works with a default configuration:
const superagent = require('superagent');
app.configure(restClient.superagent(superagent));
Axios
Axios currently works with a default configuration:
const axios = require('axios');
app.configure(restClient.axios(axios));
Fetch
Fetch also uses a default configuration:
const fetch = require('node-fetch');
app.configure(restClient.fetch(fetch));
Direct connection
You can communicate with a Feathers server using any HTTP REST client. The following section describes what HTTP method, body and query parameters belong to which service method call.
All query parameters in a URL will be set as params.query on the server. Other service parameters can be set through hooks and Express middleware. URL query parameter values will always be strings. Conversion (e.g. the string 'true' to boolean true) can be done in a hook as well.
The body type for POST, PUT and PATCH requests is determined by the Express body-parser middleware which has to be registered before any service. You should also make sure you are setting your Accept header to application/json.
find
Retrieves a list of all matching resources from the service
GET /messages?status=read&user=10
Will call messages.find({ query: { status: 'read', user: '10' } }) on the server.
If you want to use any of the built-in find operands ($le, $lt, $ne, $eq, $in, etc.) the general format is as follows:
GET /messages?field[$operand]=value&field[$operand]=value2
For example, to find the records where field status is not equal to active you could do
GET /messages?status[$ne]=active
More information about the possible parameters for official database adapters can be found in the database querying section.
get
Retrieve a single resource from the service.
GET /messages/1
Will call messages.get(1, {}) on the server.
GET /messages/1?fetch=all
Will call messages.get(1, { query: { fetch: 'all' } }) on the server.
create
Create a new resource with data which may also be an array.
POST /messages
{ "text": "I really have to iron" }
Will call messages.create({ "text": "I really have to iron" }, {}) on the server.
POST /messages
[
{ "text": "I really have to iron" },
{ "text": "Do laundry" }
]
update
Completely replace a single or multiple resources.
PUT /messages/2
{ "text": "I really have to do laundry" }
Will call messages.update(2, { "text": "I really have to do laundry" }, {}) on the server. When no id is given by sending the request directly to the endpoint something like:
PUT /messages?complete=false
{ "complete": true }
Will call messages.update(null, { "complete": true }, { query: { complete: 'false' } }) on the server.
ProTip:
updateis normally expected to replace an entire resource which is why the database adapters only supportpatchfor multiple records.
patch
Merge the existing data of a single or multiple resources with the new data.
PATCH /messages/2
{ "read": true }
Will call messages.patch(2, { "read": true }, {}) on the server. When no id is given by sending the request directly to the endpoint something like:
PATCH /messages?complete=false
{ "complete": true }
Will call messages.patch(null, { complete: true }, { query: { complete: 'false' } }) on the server to change the status for all read messages.
This is supported out of the box by the Feathers database adapters
remove
Remove a single or multiple resources:
DELETE /messages/2?cascade=true
Will call messages.remove(2, { query: { cascade: 'true' } }).
When no id is given by sending the request directly to the endpoint something like:
DELETE /messages?read=true
Will call messages.remove(null, { query: { read: 'true' } }) to delete all read messages.


