How to Detect If a Server Is Using Spdy

How to detect if a server is using SPDY

openssl s_client -connect google.com:443 -nextprotoneg ''
CONNECTED(00000003)
Protocols advertised by server: spdy/3.1, spdy/3, http/1.1

How can I detect, server side, if the client supports SPDY?

All data is sensitive: the sites you visit, the pages you've viewed, etc. By aggregating this data across many pages, you can infer a lot about the user: their intent, interests, and so on. Hence, we need HTTPS everywhere. For more, see our Google I/O talk [1] on the subject.

In terms of detecting SPDY support, yes you want to use NPN/ALPN (ALPN is a successor [2]). The client sends a ProtocolNameList in their handshake, which advertises which protocols they support. Most servers will use this to auto-negotiate SPDY, but if you want to control this decision yourself, you'd have to modify your server implementation to invoke some sort of callback when the secure handshake is being performed.

That said, given what I said earlier about HTTPS everywhere, I would advise you against this altogether. Use HTTPS everywhere and let the browser and server auto-negotiate SPDY if its supported.

  • [1] https://www.youtube.com/watch?v=cBhZ6S0PFCY
  • [2] http://chimera.labs.oreilly.com/books/1230000000545/ch04.html#ALPN

How to tell an server that client supports SPDY protocol?

When the client performs the SSL handshake the server needs to advertise spdy via the NPN extension. Here are a couple of links for more details:

  • http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft2#TOC-Server-Advertisement-of-SPDY-throug1
  • https://datatracker.ietf.org/doc/html/draft-agl-tls-nextprotoneg-00.html

Detect HTTP2/SPDY Support in Browser

Thanks, Patrick. I took your advice and leveraged nginx's $http2 variable and used PHP to return a dynamic JS variable for the browser's detection. (Passing a cookie or adding a response header for AJAX detection are also options if other readers prefer).

NGINX config additions

server {
...

if ($http2) {
rewrite ^/detect-http2.js /detect-http2.js.php?http2=$http2 last;
}
# fallback to non-HTTP2 rewrite
rewrite ^/detect-http2.js /detect-http2.js.php last;

# add response header if needed in the future
add_header x-http2 $http2;
}

detect-http2.js.php

<?
header('content-type: application/javascript');
if (isset($_REQUEST['http2'])) {
echo "var h2Version='". $_REQUEST['http2'] . "';\n";
}
?>

detect-http2.html

<html>
<body>
<script src="https://DOMAIN_NAME/detect-http2.js"></script>
<script>
document.write('HTTP2-Supported Browser: '+ (typeof h2Version !== 'undefined'));
</script>
</body>
</html>

Detect connection protocol (HTTP/2, spdy) from javascript

It is being standardised as performance.timing.nextHopProtocol, but chrome has a non-standard implementation already under window.chrome.loadTimes().connectionInfo:

if ( window.performance && performance.timing.nextHopProtocol ) {
console.log('Protocol:' + performance.timing.nextHopProtocol);
} else if (window.performance && window.performance.getEntries) {
console.log(performance.getEntries()[0].nextHopProtocol);
} else if ( window.chrome && window.chrome.loadTimes ) {
console.log('Protocol:' + window.chrome.loadTimes().connectionInfo);
} else {
console.log("Browser does not expose connection protocol");
}

HTTP2 / SPDY Push-Stream Verification: How to Test?

Within the Chrome inspector, I discovered it is quite easily recognized when a resource has been pushed by the server.

First: Within the network view/tab, the resource(s) in question will show virtually no request sent and 'waiting(TTFB)' in the waterfall (See image below).

The theme.min.css & theme.min.js resources are pushed:

Sample Image

Second: After clicking on the pushed the resource(s), opening the "Headers" pane and inspecting the "Request Headers" panel at the bottom, check for Provisional headers are shown. If the warning is shown for the resource, then it was pushed. See this SO answer to why you will see this warning.

Headers Inspector:

Sample Image

If you need a little more detailed information about the pushed resource(s), using the chrome://net-internals/#http2 method as stated in the second part of @josh3736 answer would work too. But if you need a quick way to verify that the resource(s) has been pushed and excepted by the client, viewing the waterfall will show this.

How to check if a website has HTTP/2 protocol support

You can just check it in: Chrome Dev Tool (F12) → NetworkProtocol.

It will tell you the protocol used and the domain of each transfer.

Chrome Dev Tool (F12) -> Network -> Protocol

Legend

http/1.1 = HTTP/1.1

h2          = HTTP/2


Note: If you cannot see the Protocol column, just right-click on any header and check the "Protocol" label.



Related Topics



Leave a reply



Submit