Did you know? All Video & Audio API plans include a $100 free usage credit each month so you can build and test risk-free. View Plans ->

Bidirectional-streams Over Synchronous HTTP (BOSH)

When building an app incorporating real-time communication features, you may encounter situations where WebSockets are impractical or incompatible.

The Bidirectional-streams Over Synchronous HTTP (BOSH) protocol may be a viable alternative for restricted networks or legacy devices.

What Is BOSH?

BOSH is a transport protocol that enables bidirectional communication between XMPP clients and servers over HTTP by keeping one or two HTTP requests open at all times. This approach reduces unnecessary network traffic and improves responsiveness on restrictive networks.

BOSH is considerably less common than it used to be, having largely been replaced by the WebSocket protocol due to its ability to maintain true persistent, low-latency connections without the overhead of repeated HTTP requests.

One scenario where BOSH is still well-suited is for web and mobile clients operating on unstable networks, where it's difficult to maintain a persistent TCP connection.

For example, developers can use BOSH for users with weak connections in an instant messaging app.

How Does BOSH Work?

Here is how BOSH achieves persistent connections:

Long Polling and Concurrent Connections

BOSH employs an optimized form of long polling to simulate a concurrent connection.

The client sends an HTTP request to the server, which is often handled by a specialized connection manager (CM), typically running alongside an XMPP server. The server holds this request open until data is available to send back to the client or a timeout occurs.

Rather than having the client connect directly to the server, the CM handles all HTTP traffic. It receives and parses client requests and handles session state, enabling message delivery, session resumption, and message batching.

As soon as the server responds, the client immediately opens a new HTTP connection, making sure there is always at least one open connection ready to receive messages.

Session Management

BOSH sessions begin with the client's request to the CM for a new session. The request's <body/> element contains the attributes needed to create a session.

Here is an example of a typical session request:

POST /webclient HTTP/1.1

Host: httpcm.example.com

Content-Type: text/xml; charset=utf-8

<body from='user@getstream.io'\
          hold='1'

           rid='3911287258'\
          to='getstream.io'\
          wait='60'\
          xmlns='http://jabber.org/protocol/httpbind' />

The server then responds with a session ID (sid) and other attributes, such as inactivity:

HTTP/1.1 200 OK

Content-Type: text/xml; charset=utf-8

<body sid='SomeSID'

           wait='60'

           hold='1' 

           inactivity='30' 

           requests='2' 

           xmlns='http://jabber.org/protocol/httpbind '/>

The attributes used inside the <body/> are:

  • rid is the request ID that uniquely identifies each request.
  • sid is a unique session identifier.
  • from declares the client's Jabber ID (JID) for the session.
  • wait sets the long polling timeout.
  • hold defines the maximum number of requests held open.
  • requests limits simultaneous requests.
  • inactivity is the maximum number of seconds of idle time before session closure.
  • polling specifies the shortest interval between requests.

Request Handling

With an active BOSH session, the client and server exchange data via sequential HTTP POST requests and responses containing XMPP stanzas (XML fragments) wrapped in a <body/> element.

Here is an example of a request:

POST /webclient HTTP/1.1

Host: httpcm.getstream.io

Content-Type: text/xml; charset=utf-8

Content-Length: 279

<body  rid='3911287259'\
            sid='SomeSID' 

xmlns='http://jabber.org/protocol/httpbind'>

  <message to='contact@getstream.io' 

        xmlns='jabber:client'>

    <body>Hello, how is everything?</body>

  </message>

</body>

A typical response looks like the following:

HTTP/1.1 200 OK

Content-Type: text/xml; charset=utf-8

Content-Length: 917

<body xmlns='http://jabber.org/protocol/httpbind'>

  <message from='contact@getstream.io'

        to='user@getstream.io' 

        xmlns='jabber:client'>

    <body>Hello, everything is okay!</body>

  </message>

</body>

The CM guarantees in-order delivery by matching responses to their corresponding request IDs. It can also batch multiple messages into a single response if necessary, maintaining session continuity in case the connection is interrupted.

Applications of BOSH

While BOSH was once a more widely utilized communication transport protocol, its use cases are niche and specialized today.

Some situations where BOSH remains relevant include:

XMPP Messaging Applications

BOSH is commonly used for client/server messaging apps built on XMPP. It can also be used in more complex setups, such as multi-user group chats like community forums, thanks to its optional support for multiple logical streams in a single session.

It's important to note that these applications will likely be run in legacy environments where modern protocols are not supported.

Cross-Network Communication. 

BOSH can work in scenarios where traditional TCP connections do not, as it operates over HTTP. It helps bypass network barriers such as proxies and firewalls that block non-HTTP traffic. 

BOSH vs WebSockets

BOSH and WebSockets have many features in common, such as creating persistent connections between the client and the server. However, they differ significantly in their approach, performance, and use cases.

Some of the key differences include:

Latency

BOSH relies on HTTP long polling, which introduces slight delays due to the request-response cycle. However, its latency is usually low enough to support real-time chat use cases. WebSocket achieves low latency by creating a persistent TCP connection for instant data transfer.

Packet Overhead 

The headers in requests and responses can cause packet overhead, even though the CM batches multiple messages into a single response. This overhead makes it less efficient for small, frequent packets.

WebSockets avoids HTTP overhead, making it more efficient for small packets. Data travels through the established connection, which is ideal for high-frequency update apps.

Learning Curve

BOSH is more complex to learn and implement due to session management and long polling mechanisms. These require careful handling of request IDs, session IDs, continuity, and concurrent connections.

WebSockets are generally simple to implement, requiring only establishing a handshake and a persistent connection.

Use Cases

As stated above, BOSH excels in environments with network constraints and restrictions. It can work seamlessly in apps with inconsistent networks and older systems where WebSockets would not work efficiently.

WebSockets are suitable for apps that need low-latency and high-frequency updates, such as live events, online gaming, telehealth, and more.

Best Practices for Implementing BOSH

To implement BOSH effectively, follow these guidelines:

Configure the Server To Handle Prolonged Connections

BOSH's long polling mechanism requires servers to manage prolonged HTTP connections. Therefore, when configuring your server, set appropriate timeouts using the wait attribute.

This prevents the premature disconnection of HTTP requests. Also, make sure the server can manage multiple concurrent connections, as BOSH typically holds up to two requests simultaneously (hold='1', requests='2') to support bidirectional communication without overloading resources.

Manage Connections Properly

Proper connection management ensures the server and client can exchange data concurrently without conflicts. Using sid, you can maintain continuity across requests and use the same rid to re-establish sessions after network interruptions.

You should also monitor the inactivity period (usually 30 seconds) and send empty <body/> responses to keep sessions alive. This prevents the session from terminating due to idle connections.

Implement Security Measures

Additional security measures are needed to safeguard BOSH traffic over HTTP. By using HTTPS, you can encrypt data, protecting sensitive payloads like XMPP stanzas.

To make sure only authorized users can create sessions, implement proper authentication. BOSH uses attributes to verify identities when creating sessions, such as from.

Optimize Server Performance

You can reduce overhead by batching multiple messages into a single HTTP request. Also, you must adjust the polling interval (using the polling attribute) based on traffic patterns to avoid overactivity.

Frequently Asked Questions

What Is the Difference Between BOSH and XMPP?

BOSH is a transport protocol that uses HTTP polling to enable XMPP communication over HTTP.

On the other hand, XMPP is an XML-based messaging protocol that developers use for instant messaging. While it operates on a decentralized network model, individual clients connect to specific XMPP servers to send and receive messages within their domain.

How Does BOSH Differ From Traditional HTTP Polling Methods?

BOSH uses long polling to keep requests open while awaiting data to send a response to the client and close the request. Traditional HTTP polling requires numerous client requests, even when no data is available.

What Are the Primary Use Cases of BOSH in Real-Time Applications?

BOSH is used for communication in real-time applications working on inconsistent networks. It also works in legacy systems where WebSockets would not be suitable.