REST Client
===========
.. note:: For directly using a Feathers REST API (via HTTP) without
using Feathers on the client see the :ref:`api_client_rest_http-api`
section.
@feathersjs/rest-client
-----------------------
|GitHub stars| |npm version| |Changelog|
.. code-block:: sh
$ npm install @feathersjs/rest-client --save
``@feathersjs/rest-client`` allows to connect to a service exposed
through the :ref:`api_express_rest` using
`jQuery `_,
`request `_,
`Superagent `_,
`Axios `_ or
`Fetch `_ as
the AJAX library.
.. raw:: html
..
.. tip:: REST client services do emit ``created``, ``updated``,
``patched`` and ``removed`` events but only *locally for their own
instance*. Real-time events from other clients can only be received
by using a websocket connection.
.. raw:: html
..
.. 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
``@feathersjs/rest-client`` and initializing a client object with a base
URL:
.. code-block:: js
const feathers = require(‘@feathersjs/feathers’);
const rest = require(‘@feathersjs/rest-client’);
const app = feathers();
// Connect to the same as the browser URL (only in the browser)
const restClient = rest();
// Connect to a different URL
const restClient = rest(‘http://feathers-api.com’)
// Configure an AJAX library (see below) with that client
app.configure(restClient.fetch(window.fetch));
// Connect to the ``http://feathers-api.com/messages`` service
const messages = app.service(‘messages’);
.. raw:: html
.. tip:: In the browser, the base URL is relative from where
services are registered. That means that a service at
``http://api.feathersjs.com/api/v1/messages`` with a base URL of
``http://api.feathersjs.com`` would be available as
``app.service('api/v1/messages')``. With a base URL of
``http://api.feathersjs.com/api/v1`` it would be
``app.service('messages')``.
params.headers
~~~~~~~~~~~~~~
Request specific headers can be through ``params.headers`` in a service
call:
.. code:: js
app.service('messages').create({
text: 'A message from a REST client'
}, {
headers: { 'X-Requested-With': 'FeathersJS' }
});
params.connection
~~~~~~~~~~~~~~~~~
Allows to pass additional options specific to the AJAX library.
``params.connection.headers`` will be merged with ``params.headers``:
.. code:: js
app.configure(restClient.request(request));
app.service('messages').get(1, {
connection: {
followRedirect: false
}
});
With the ``fetch`` fork `yetch `_ it
can also be used to abort requests:
.. code:: js
const yetch = require('yetch');
const controller = new AbortController();
app.configure(restClient.fetch(yetch));
const promise = app.service('messages').get(1, {
connection: {
signal: controller.signal
}
});
promise.abort();
jQuery
~~~~~~
Pass the instance of jQuery (``$``) to ``restClient.jquery``:
.. code:: js
app.configure(restClient.jquery(window.jQuery));
Or with a module loader:
.. code:: js
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:
.. code:: js
const request = require('request');
const requestClient = request.defaults({
'auth': {
'user': 'username',
'pass': 'password',
'sendImmediately': false
}
});
app.configure(restClient.request(requestClient));
Superagent
~~~~~~~~~~
`Superagent `_ currently
works with a default configuration:
.. code:: js
const superagent = require('superagent');
app.configure(restClient.superagent(superagent));
Axios
~~~~~
`Axios `_ currently works with a
default configuration:
.. code:: js
const axios = require('axios');
app.configure(restClient.axios(axios));
Fetch
~~~~~
Fetch also uses a default configuration:
.. code:: js
// In Node
const fetch = require('node-fetch');
app.configure(restClient.fetch(fetch));
// In modern browsers
app.configure(restClient.fetch(window.fetch));
.. _api_client_rest_http-api:
HTTP API
--------
You can communicate with a Feathers REST API using any other 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
:doc:`../express`. 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``.
.. _api-client-rest-authentication:
Authentication
~~~~~~~~~~~~~~
Authenticating HTTP (REST) requests is a two step process. First you
have to obtain a JWT from the :doc:`../authentication/server`
by POSTing the strategy you want to use:
.. code-block:: json
:caption: POST /authentication the Content-Type header set to application/json
{
"strategy": "local",
"email": "your email",
"password": "your password"
}
Here is what that looks like with curl:
.. code:: bash
curl -H "Content-Type: application/json" -X POST -d '{"strategy":"local","email":"your email","password":"your password"}' http://localhost:3030/authentication
Then to authenticate subsequent requests, add the returned
``accessToken`` to the ``Authorization`` header:
.. code:: bash
curl -H "Content-Type: application/json" -H "Authorization: " -X POST http://localhost:3030/authentication
Also see the :doc:`../authentication/jwt` and :doc:`../authentication/local` authentication chapter.
find
~~~~
Retrieves a list of all matching resources from the service
.. code-block:: sh
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:
.. code-block:: sh
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
.. code-block:: sh
GET /messages?status[$ne]=active
More information about the possible parameters for official database adapters
can be found :doc:`../databases/querying`.
get
~~~
Retrieve a single resource from the service.
.. code-block:: sh
GET /messages/1
Will call ``messages.get(1, {})`` on the server.
.. code-block:: sh
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.
.. code-block:: sh
POST /messages
{ "text": "I really have to iron" }
Will call ``messages.create({ "text": "I really have to iron" }, {})``
on the server.
.. code-block:: sh
POST /messages
[
{ "text": "I really have to iron" },
{ "text": "Do laundry" }
]
update
~~~~~~
Completely replace a single or multiple resources.
.. code-block:: sh
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:
.. code-block:: sh
PUT /messages?complete=false
{ "complete": true }
Will call
``messages.update(null, { "complete": true }, { query: { complete: 'false' } })``
on the server.
.. tip:: ``update`` is normally expected to replace an entire
resource which is why the database adapters only support ``patch``
for multiple records.
patch
~~~~~
Merge the existing data of a single or multiple resources with the new
``data``.
.. code-block:: sh
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:
.. code-block:: sh
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 :doc:`../databases/adapters`
remove
~~~~~~
Remove a single or multiple resources:
.. code-block:: sh
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:
.. code-block:: sh
DELETE /messages?read=true
Will call ``messages.remove(null, { query: { read: 'true' } })`` to
delete all read messages.
.. |GitHub stars| image:: https://img.shields.io/github/stars/feathersjs/rest-client.png?style=social&label=Star
:target: https://github.com/feathersjs/rest-client/
.. |npm version| image:: https://img.shields.io/npm/v/@feathersjs/rest-client.png?style=flat-square
:target: https://www.npmjs.com/package/@feathersjs/rest-client
.. |Changelog| image:: https://img.shields.io/badge/changelog-.md-blue.png?style=flat-square
:target: https://github.com/feathersjs/rest-client/blob/master/CHANGELOG.md