---
outline: deep
---
# REST Client
The following chapter describes the use of
- [@feathersjs/rest-client](#feathersjsrest-client) as a client side Feathers HTTP API integration
- [Direct connection](#http-api) with any other HTTP client
## rest-client
For directly using a Feathers REST API (via HTTP) without using Feathers on the client see the [HTTP API](#http-api) section.
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 real-time transport like [Socket.io](./socketio.md).
A client application can only use **a single transport** (e.g. either REST or Socket.io). Using two transports in the same client application is not necessary.### rest([baseUrl]) REST client services can be initialized by loading `@feathersjs/rest-client` and initializing a client object with a base URL. ```ts import { feathers } from '@feathersjs/feathers' import rest from '@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.bind(window))) // Connect to the `http://feathers-api.com/messages` service const messages = app.service('messages') ``` 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')` - A base URL of `http://api.feathersjs.com/api/v1` would be `app.service('messages')`.
In the browser `window.fetch` (which the same as the global `fetch`) has to be passed as `window.fetch.bind(window)` otherwise it will be called with an incorrect context, causing a JavaScript error: `Failed to execute 'fetch' on 'Window': Illegal invocation`.### params.headers Request specific headers can be through `params.headers` in a service call: ```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`: ```js app.configure(restClient.axios(axios)) app.service('messages').get(1, { connection: { // Axios specific options here } }) ``` ### app.rest `app.rest` contains a reference to the `connection` object passed to `rest().
Just like on the server _all_ methods you want to use have to be listed in the `methods` option.### Connecting to multiple servers It is possible to instantiate and use individual services pointing to different servers by calling `rest('server').
If the authentication information is different, it needs to be set as an option as shown above or via `params.headers` when making the request.### Extending rest clients This can be useful if you e.g. wish to override how the query is transformed before it is sent to the API. ```ts import type { Query } from '@feathersjs/feathers' import { FetchClient } from '@feathersjs/rest-client' import qs from 'qs' class CustomFetch extends FetchClient { getQuery(query: Query) { if (Object.keys(query).length !== 0) { const queryString = qs.stringify(query, { strictNullHandling: true }) return `?${queryString}` } return '' } } app.configure(restClient.fetch(fetch, CustomFetch)) ``` ## 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 [hooks](../hooks.md) and [Express middleware](../express.md). URL query parameter values will always be strings. Conversion (e.g. the string `'true'` to boolean `true`) on the server is done via [schemas](../schema/index.md) or [hooks](../hooks.md). The body type for `POST`, `PUT` and `PATCH` requests is determined by the request type. You should also make sure you are setting your `Accept` header to `application/json`. Here is the mapping of service methods to REST API calls: | 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 | ### Authentication Authenticating HTTP (REST) requests is a two step process. First you have to obtain a JWT from the [authentication service](../authentication/service.md) by POSTing the strategy you want to use: ```json // 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: ```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 as `Bearer
With a [database adapters](../databases/adapters.md) the [`multi` option](../databases/common.md) has to be set explicitly to support creating multiple entries.### 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?status=unread { "status": "read" } ``` Will call `messages.update(null, { status: 'read' }, { query: { status: 'unread' } })` on the server. ### patch Merge the existing data of a single or multiple resources with the new `data`. ``` PATCH /messages/2 { "status": "read" } ``` Will call `messages.patch(2, { status: 'read' }, {})` on the server. When no `id` is given by sending the request directly to the endpoint something like: ``` PATCH /messages?status=unread { "status": "read" } ``` Will call `messages.patch(null, { status: 'read' }, { query: { status: 'unread' } })` on the server to change the status for all read messages.
With a [database adapters](../databases/adapters.md) the [`multi` option](../databases/common.md) has to be set to support patching multiple entries.This is supported out of the box by the Feathers [database adapters](../databases/adapters.md) ### remove Remove a single or multiple resources: ``` DELETE /messages/2 ``` Will call `messages.remove(2, {} })`. When no `id` is given by sending the request directly to the endpoint something like: ``` DELETE /messages?status=archived ``` Will call `messages.remove(null, { query: { status: 'archived' } })` to delete all read messages.
With a [database adapters](../databases/adapters.md) the [`multi` option](../databases/common.md) has to be set to support patching multiple entries.### Custom methods [Custom service methods](../services.md#custom-methods) can be called directly via HTTP by sending a POST request and setting the `X-Service-Method` header to the method you want to call: ``` POST /messages X-Service-Method: myCustomMethod { "message": "Hello world" } ``` Via CURL: ```bash curl -H "Content-Type: application/json" -H "X-Service-Method: myCustomMethod" -X POST -d '{"message": "Hello world"}' http://localhost:3030/myservice ``` This will call `messages.myCustomMethod({ message: 'Hello world' }, {})`. ### Route placeholders Service URLs can have placeholders, e.g. `users/:userId/messages`. (see in [express](../express.md#params.route) or [koa](../koa.md#params.route)) You can call the client with route placeholders in the `params.route` property: ```ts import { feathers } from '@feathersjs/feathers' import rest from '@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.bind(window))) // Connect to the `http://feathers-api.com/messages` service const messages = app.service('users/:userId/messages') // Call the `http://feathers-api.com/users/2/messages` URL messages.find({ route: { userId: 2 } }) ``` This can also be achieved by using the client bundled, sharing several `servicePath` variable exported in the [service shared file](../../guides/cli/service.shared.md#Variables) file. ```ts import rest from '@feathersjs/rest-client' // usersMessagesPath contains 'users/:userId/messages' import { createClient, usersMessagesPath } from 'my-app' const connection = rest('https://myapp.com').fetch(window.fetch.bind(window)) const client = createClient(connection) // Call the `https://myapp.com/users/2/messages` URL client.service(usersMessagesPath).find({ route: { userId: 2 } }) ```