tl;dr curl -H 'Upgrade: websocket' -H "Sec-WebSocket-Key: `openssl rand -base64 16`" -H 'Sec-WebSocket-Version: 13' --http1.1 -sSv https://ws.ifelse.io
(depending on the server you might need to provide Origin
and/or Connection: Upgrade
)
First, how does the websocket protocol work in a few words? A client connects to a server, sends a handshake request, receives "101 Switching Protocols" (a handshake response) after which they send frames back and forth.
The handshake looks along the following lines:
GET / HTTP/1.1
Host: ws.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Version: 13
Origin: http://example.com
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Upgrade
makes it switch from HTTP(s) to the websocket protocol.
Connection
specifies that Upgrade
is a hop-by-hop header (headers that intermediaries should consume, not forward). But my experiments show that it works w/o this header. Or to be more precise, it might be optional if there's a reverse proxy in front of the server (e.g. nginx
).
Sec-WebSocket-Key
/Sec-WebSocket-Accept
is a security measure described here, here and here.
Sec-WebSocket-Version
specifies the websocket protocol version. According to RFC 6455 it should be equal 13.
Origin
is needed when the client is a browser and the origin of the requesting page doesn't match the origin of the websocket server URL.
A detailed description of what should constitute a websocket handshake request can be found here.
That's how it goes with HTTP/1.1. HTTP/2 is a different story.
Knowing this to establish a websocket connection with curl
:
$ curl -H 'Upgrade: websocket' \
-H "Sec-WebSocket-Key: `openssl rand -base64 16`" \
-H 'Sec-WebSocket-Version: 13' \
--http1.1 \
-sSv \
https://ws.ifelse.io
...
> GET / HTTP/1.1
> Host: ws.ifelse.io
> Upgrade: websocket
> Sec-WebSocket-Key: e2dujvcbYbN747lapeH+WA==
> Sec-WebSocket-Version: 13
...
< HTTP/1.1 101 Switching Protocols
< Connection: upgrade
< upgrade: websocket
< sec-websocket-accept: 6wmMGMtN00aWw3loYd6P36EHKMI=
The other options are wscat
, websocat
.