docs/api/client/socketio.md
---
outline: deep
---
# Socket.io Client
## socketio-client
<Badges>
[![npm version](https://img.shields.io/npm/v/@feathersjs/client.svg?style=flat-square)](https://www.npmjs.com/package/@feathersjs/socketio-client)
[![Changelog](https://img.shields.io/badge/changelog-.md-blue.svg?style=flat-square)](https://github.com/feathersjs/feathers/blob/dove/packages/socketio-client/CHANGELOG.md)
</Badges>
```
npm install @feathersjs/socketio-client socket.io-client --save
```
The `@feathersjs/socketio-client` module allows to connect to services exposed through the [Socket.io transport](../socketio.md) via a Socket.io socket. We recommend using Feathers and the `@feathersjs/socketio-client` module on the client if possible since it can also handle reconnection and reauthentication. If however, you want to use a direct Socket.io connection without using Feathers on the client, see the [Direct connection](#direct-connection) section.
<BlockQuote type="warning" label="Important">
Socket.io is also used to _call_ service methods. Using sockets for both calling methods and receiving real-time events is generally faster than using [REST](./rest.md). There is therefore no need to use both REST and Socket.io in the same client application.
</BlockQuote>
### socketio(socket)
Initialize the Socket.io client using a given socket and the default options.
```ts
import { feathers } from '@feathersjs/feathers'
import socketio from '@feathersjs/socketio-client'
import io from 'socket.io-client'
const socket = io('http://api.feathersjs.com')
const app = feathers()
// Set up Socket.io client with the socket
app.configure(socketio(socket))
// Receive real-time events through Socket.io
app.service('messages').on('created', (message) => console.log('New message created', message))
// Call the `messages` service
app.service('messages').create({
text: 'A message from a REST client'
})
```
### `app.io`
`app.io` contains a reference to the `socket` object passed to `socketio(socket [, options])`
```ts
app.io.on('disconnect', (reason: any) => {
// Show offline message
})
```
### Custom Methods
On the client, [custom service methods](../services.md#custom-methods) are also registered using the `methods` option when registering the service via `socketClient.service()`:
```ts
import { feathers } from '@feathersjs/feathers'
import type { Params } from '@feathersjs/feathers'
import socketio from '@feathersjs/socketio-client'
import type { SocketService } from '@feathersjs/socketio-client'
import io from 'socket.io-client'
// `data` and return type of custom method
type CustomMethodData = { name: string }
type CustomMethodResponse = { acknowledged: boolean }
type ServiceTypes = {
// The type is a Socket service extended with custom methods
myservice: SocketService & {
myCustomMethod(data: CustomMethodData, params: Params): Promise<CustomMethodResponse>
}
}
const socket = io('http://api.feathersjs.com')
const client = feathers<ServiceTypes>()
const socketClient = socketio(socket)
// Set up Socket.io client with the socket
client.configure(socketClient)
// Register a socket client service with all methods listed
client.use('myservice', socketClient.service('myservice'), {
methods: ['find', 'get', 'create', 'update', 'patch', 'remove', 'myCustomMethod']
})
// Then it can be used like other service methods
client.service('myservice').myCustomMethod(data, params)
```
<BlockQuote type="info">
Just like on the server _all_ methods you want to use have to be listed in the `methods` option.
</BlockQuote>
### 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 socketio from '@feathersjs/socketio-client'
import io from 'socket.io-client'
const socket = io('http://api.feathersjs.com')
const app = feathers()
// Set up Socket.io client with the socket
app.configure(socketio(socket))
// Call `users/2/messages`
app.service('users/:userId/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'
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(usersMyMessagesPath).find({
route: {
userId: 2
}
})
import io from 'socket.io-client'
import socketio from '@feathersjs/socketio-client'
import { createClient, usersMessagesPath } from 'my-app'
const socket = io('http://api.my-feathers-server.com')
const connection = socketio(socket)
const client = createClient(connection)
const messageService = client.service('users/:userId/messages')
// Call `users/2/messages`
app.service('users/:userId/messages').find({
route: {
userId: 2
}
})
```
## Direct connection
Feathers sets up a normal Socket.io server that you can connect to with any Socket.io compatible client, usually the [Socket.io client](http://socket.io/docs/client-api/) either by loading the `socket.io-client` module or `/socket.io/socket.io.js` from the server. Query parameter types do not have to be converted from strings as they do for REST requests.
<BlockQuote type="warning" label="Important">
The socket connection URL has to point to the server root which is where Feathers will set up Socket.io.
</BlockQuote>
```html
<!-- Connecting to the same URL -->
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io()
</script>
<!-- Connecting to a different server -->
<script src="http://localhost:3030/socket.io/socket.io.js"></script>
<script>
var socket = io('http://localhost:3030/')
</script>
```
Service methods can be called by emitting a `<methodname>` event followed by the service path and method parameters. The service path is the name the service has been registered with (in `app.use`), without leading or trailing slashes. An optional callback following the `function(error, data)` Node convention will be called with the result of the method call or any errors that might have occurred.
`params` will be set as `params.query` in the service method call. Other service parameters can be set through a [Socket.io middleware](../socketio.md).
If the service path or method does not exist, an appropriate Feathers error will be returned.
### Authentication
There are two ways to establish an authenticated Socket.io connection. Either by calling the authentication service or by sending authentication headers.
#### Via authentication service
Sockets will be authenticated automatically by calling [.create](#create) on the [authentication service](../authentication/service.md):
```ts
import io from 'socket.io-client'
const socket = io('http://localhost:3030')
socket.emit(
'create',
'authentication',
{
strategy: 'local',
email: 'hello@feathersjs.com',
password: 'supersecret'
},
function (error, authResult) {
console.log(authResult)
// authResult will be {"accessToken": "your token", "user": user }
// You can now send authenticated messages to the server
}
)
```
<BlockQuote type="warning" label="Important">
When a socket disconnects and then reconnects, it has to be authenticated again before making any other request that requires authentication. This is usually done with the [jwt strategy](../authentication/jwt.md) using the `accessToken` from the `authResult`. The [authentication client](../authentication/client.md) handles this already automatically.
</BlockQuote>
```js
socket.on('connect', () => {
socket.emit(
'create',
'authentication',
{
strategy: 'jwt',
accessToken: authResult.accessToken
},
function (error, newAuthResult) {
console.log(newAuthResult)
}
)
})
```
#### Via handshake headers
If the authentication strategy (e.g. JWT or API key) supports parsing headers, an authenticated websocket connection can be established by adding the information in the [extraHeaders option](https://socket.io/docs/client-api/#With-extraHeaders):
```ts
import io from 'socket.io-client'
const socket = io('http://localhost:3030', {
extraHeaders: {
Authorization: `Bearer <accessToken here>`
}
})
```
<BlockQuote type="info" label="Note">
The authentication strategy needs to be included in the [`authStrategies` configuration](../authentication/service.md#configuration).
</BlockQuote>
### find
Retrieves a list of all matching resources from the service
```js
socket.emit('find', 'messages', { status: 'read', user: 10 }, (error, data) => {
console.log('Found all messages', data)
})
```
Will call `app.service('messages').find({ query: { status: 'read', user: 10 } })` on the server.
### get
Retrieve a single resource from the service.
```js
socket.emit('get', 'messages', 1, (error, message) => {
console.log('Found message', message)
})
```
Will call `app.service('messages').get(1, {})` on the server.
```js
socket.emit('get', 'messages', 1, { status: 'read' }, (error, message) => {
console.log('Found message', message)
})
```
Will call `app.service('messages').get(1, { query: { status: 'read' } })` on the server.
### create
Create a new resource with `data` which may also be an array.
```js
socket.emit(
'create',
'messages',
{
text: 'I really have to iron'
},
(error, message) => {
console.log('Todo created', message)
}
)
```
Will call `app.service('messages').create({ text: 'I really have to iron' }, {})` on the server.
```js
socket.emit('create', 'messages', [{ text: 'I really have to iron' }, { text: 'Do laundry' }])
```
Will call `app.service('messages').create` with the array.
### update
Completely replace a single or multiple resources.
```js
socket.emit(
'update',
'messages',
2,
{
text: 'I really have to do laundry'
},
(error, message) => {
console.log('Todo updated', message)
}
)
```
Will call `app.service('messages').update(2, { text: 'I really have to do laundry' }, {})` on the server. The `id` can also be `null` to update multiple resources:
```js
socket.emit(
'update',
'messages',
null,
{
status: 'unread'
},
{ status: 'read' }
)
```
Will call `app.service('messages').update(null, { status: 'read' }, { query: { satus: 'unread' } })` on the server.
### patch
Merge the existing data of a single or multiple resources with the new `data`.
```js
socket.emit(
'patch',
'messages',
2,
{
read: true
},
(error, message) => {
console.log('Patched message', message)
}
)
```
Will call `app.service('messages').patch(2, { read: true }, {})` on the server. The `id` can also be `null` to update multiple resources:
```js
socket.emit(
'patch',
'messages',
null,
{
status: 'read'
},
{
status: 'unread'
},
(error, message) => {
console.log('Patched message', message)
}
)
```
Will call `app.service('messages').patch(null, { status: 'read' }, { query: { status: 'unread' } })` on the server, to change the status for all read app.service('messages').
### remove
Remove a single or multiple resources:
```js
socket.emit('remove', 'messages', 2, {}, (error, message) => {
console.log('Removed a message', message)
})
```
Will call `app.service('messages').remove(2, {})` on the server. The `id` can also be `null` to remove multiple resources:
```js
socket.emit('remove', 'messages', null, { status: 'archived' })
```
Will call `app.service('messages').remove(null, { query: { status: 'archived' } })` on the server to delete all messages with status `archived`.
### Custom methods
[Custom service methods](../services.md#custom-methods) can be called directly via Socket.io by sending a `socket.emit(methodName, serviceName, data, query)` message:
```js
socket.emit('myCustomMethod', 'myservice', { message: 'Hello world' }, {}, (error, data) => {
console.log('Called myCustomMethod', data)
})
```
### Listening to events
Listening to service events allows real-time behaviour in an application. [Service events](../events.md) are sent to the socket in the form of `servicepath eventname`.
#### created
The `created` event will be published with the callback data, when a service `create` returns successfully.
```ts
const socket = io('http://localhost:3030/')
socket.on('messages created', (message: Message) => {
console.log('Got a new Todo!', message)
})
```
#### updated, patched
The `updated` and `patched` events will be published with the callback data, when a service `update` or `patch` method calls back successfully.
```ts
const socket = io('http://localhost:3030/')
socket.on('my/messages updated', (message: Message) => {
console.log('Got an updated Todo!', message)
})
socket.emit(
'update',
'my/messages',
1,
{
text: 'Updated text'
},
{},
(error, callback) => {
// Do something here
}
)
```
#### removed
The `removed` event will be published with the callback data, when a service `remove` calls back successfully.
```js
const socket = io('http://localhost:3030/')
socket.on('messages removed', (message: Message) => {
// Remove element showing the Todo from the page
$('#message-' + message.id).remove()
})
```
#### Custom events
[Custom events](../events.md#custom-events) can be listened to accordingly:
```ts
const socket = io('http://localhost:3030/')
socket.on('messages myevent', function (data: any) {
console.log('Got myevent event', data)
})
```