joffrey-bion / krossbow

A Kotlin multiplatform coroutine-based STOMP client over websockets, with built-in conversions.
MIT License
200 stars 15 forks source link

Add websocket subprotocol negotiation for STOMP #497

Closed joffrey-bion closed 5 months ago

joffrey-bion commented 5 months ago

Problem / use case

The web socket protocol defines a way to negotiate subprotocols via the Sec-WebSocket-Protocol header. STOMP is one such subprotocol, and has several values registered in IANA's WebSocket Subprotocol Name Registry: v10.stomp, v11.stomp, v12.stomp.

While sending this header is technically not mandated by the STOMP spec, some servers might decide that they require the header in order to speak the STOMP protocol (which is a valid requirement to set), in which case Krossbow simply cannot communicate with them.

Also, some servers such as ActiveMQ don't actually respect the web socket spec entirely, and may return a protocol in Sec-WebSocket-Protocol even though none was sent by the client. This breaks some strict client implementations (such as Darwin's NSURLSessionWebSocketTask), which actively check that the negotiated protocol was sent by the client (see https://github.com/joffrey-bion/krossbow/issues/492).

Feature (solution)

It would be more correct for the Krossbow client to specify that it wants to speak STOMP v1.2 by sending the Sec-WebSocket-Protocol=v12.stomp header.

Going further, we could consider sending all 3 header values, and making sure we adjust Krossbow's behaviour based on the version selected by the server. Essentially, we could support older versions of STOMP through this negotiation.

Current alternatives

It is not always possible. In some client implementations like Ktor, we can define a default request with the header, but that's quite a hack. In most other client implementations, we simply can't do anything to make Krossbow send that header.

joffrey-bion commented 5 months ago

Summary of changes between protocol versions

Changes from 1.0 to 1.1

STOMP 1.1 is designed to be backwards compatible with STOMP 1.0 while introducing several new features not present in STOMP 1.0:

Changes from 1.1 to 1.2

STOMP 1.2 is mostly backwards compatible with STOMP 1.1. There are only two incompatible changes:

Apart from these, STOMP 1.2 introduces no new features but focuses on clarifying some areas of the specification such as:

What Krossbow should do with negotiated version

Things that don't need to change

Things to change