The Forwarded header

Obtaining client data via the “Forwarded” header

In a typical setup where the web server handles static files and passes requests to an inner application, there is some information about visitors to the site that can only be collected by the web server. The mechanism to pass on this information to the browser is the “Forwarded” header.

At present, SimmerCat passes the following data to the inner application via said header:

  • IP address of the client

  • Protocol used by the client to establish a connection

  • If the client has HTTP/2 Push enabled.

  • The internal session id of the client.

  • If sufficient data has been exchanged between the server and the client, some latency information is also provided.

This information is passed through a header that ShimmerCat stamps in the request forwarded to the inner application. The name of the header is “Forwarded”, and it is standardized by RFC 7239.

To see this header, you can configure an API domain and then invoke ShimmerCat with the option --show-proxied-headers

The Forwarded header field looks like this:

forwarded: for=;server=shimmercat;protocol=h2;push-enabled=1;session-id=1;latency=pkt2->62/pkt3->1/pkt5->2189

The different parts of the header field are separated with a semicolon (as per the RFC). The contents of the sub-fields are described in the following sub-sections.

Source IP address: “for”

This is the source IP address of the client’s connection to the server, in the usual dot-separated format, example: “”.

Distinguishing between HTTP/1.1 and HTTP/2 clients: “protocol”

This sub-field can have two values: http/1.1 or h2. The first indicates that the client is using HTTP/1.1, and the second indicates that HTTP/2 is being used.

Since ShimmerCat is a HTTPS-only server, we have omitted the proto sub-field, whose value should be assumed to be always “https”.

Determining if the client enabled HTTP/2 Push: “push-enabled”

This sub-field contains the value 1 if SETTINGS_ENABLE_PUSH by the client is 1 or still has the default value of 1 (see section 6.52 of RFC 7540). Otherwise, it contains the value 0.

Separating clients by the TCP socket they are using: “session-id”

The session-id field contains a number which is unique for each TCP connection that ShimmerCat has open. Additionally, these numbers are reported in many ShimmerCat log messages in the form C/123

Client latency: “latency”

Client latency is determined by sending HTTP/2 ping frames to the client in a few occasions. Each of those occasions is represented in the value of the latency sub-field.



The format is pkt#->TTT/..., where # represents an internal sequence number assigned by ShimmerCat and TTT represents the time in milliseconds between sending the ping frame and receiving the corresponding ping acknowledgment from the client.

The sequence numbers are not consecutive, since they are not used exclusively for ping frames.

We do our best to short-circuit processing of Ping frames inside ShimmerCat, so that the reported latency is as accurate as possible. However, this is still a work in progress, and due to network congestion and intricacies with the internal evented architecture of ShimmerCat, you should consider the latency data as approximate and use the minimum of all the values present in the sub-field.

Notice that the latency sub-field is not present for HTTP/1.1 clients.