HTTP Upgrade using REST in NodeJS (Practical Example)

Onsurity
3 min readMar 24, 2022

HTTP Upgrade feature can be used to upgrade an already established client/server connection to a different protocol (must be over the same transport protocol). It was introduced in HTTP/1.1. Check the IETF doc.

Using this method one can upgrade the existing HTTP connection to HTTP 2.0 or HTTPS or even a bi-directional connection. ( Websocket ).

### This feature has been deprecated in HTTP 2.0 versions.

If a client wants to upgrade the underlying HTTP protocol, it starts the initial handshake by sending The Upgrade header field in the request as per .

The Upgrade header field only applies to the immediate connection and as it works hop-to-hop, it also needs to be listed in the Connection header.

A typical HTTP upgrade request looks like this…

GET/chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com

If the server agrees on the upgrade, then it sends back a 101 Switching Protocol response. If the server does not agree to the upgrade, then it sends back a regular response ( Eg. 200 / 400 ). Right after sending the 101 status code, the server can begin speaking the new protocol. As soon as the upgrade response is complete, the connection becomes a two-way pipe.

A typical server response looks like this…

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat

In this session, we will write a Websocket upgrade with a typical REST API and I will show you, from scratch, how to do it.

A WebSocket is a persistent connection between a client and a server. WebSockets provide a bidirectional, full-duplex communications channel that operates over HTTP through a single TCP/IP socket connection. Check this IETF doc.

It is a layer 7 protocol of the OSI Model and works under TCP at layer 4.

Client-Side initiatives…

Or Using Fetch API below is the request pattern

Sec-WebSocket-Version: 13
Sec-WebSocket-Key: kfp9XPVd4Xs5kktlrU6/0Q==
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
Host: 0.0.0.0:4000

Sec-WebSocket-Key
Provides information to the server which is needed in order to confirm that the client is entitled to request an upgrade to WebSocket.

Sec-WebSocket-Extensions
Specifies one or more protocol-level WebSocket extensions to ask the server to use. Using more than one Sec-WebSocket-Extension header in a request is permitted.

Server-Side (I have written it in Fastify framework)

fastify.get('/sock-test',async (request, response)=>{
let magic_string = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
let websocket_key = request.headers["sec-websocket-key"];
let concat_string = websocket_key + magic_string
var shasum = crypto.createHash('sha1')
shasum.update(concat_string)
let encrypted_data = shasum.digest('base64')
console.log(encrypted_data)
response
.code(101)
.headers({
'Upgrade': 'websocket',
'Connection': 'Upgrade',
'Sec-WebSocket-Accept': encrypted_data,
'Sec-WebSocket-Version':13

Sec-WebSocket-Version
A comma-delimited list of the WebSocket protocol versions supported by the server.

Sec-WebSocket-Accept (Important)
The server takes the value of the Sec-WebSocket-Key sent in the handshake request, appends 258EAFA5-E914–47DA-95CA-C5AB0DC85B11 (Magic String), takes SHA-1 of the new value, and is then base64 encoded, resulting in a 20-byte value. (Don’t use HEXDigest).

In Chrome it looks like this

Typical WebSocket example in chrome

Give me a thumbs up if you can implement it yourself. If you have any questions, please write them in the comment section.

Additional Reads

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Upgrade
https://www.rfc-editor.org/rfc/rfc2616#section-14.42
https://httpwg.org/specs/rfc7230.html#header.upgrade

Originally published at https://subhajit-dutta.medium.com on March 24, 2022.

--

--