Home > Mobile >  How to check if a website supports HTTP/2 in Python
How to check if a website supports HTTP/2 in Python

Time:09-05

I'm trying to get 101 Switching Protocol response by upgrading the connnection to HTTP/2 via Socket. I've tried big web that support HTTP/2 such as google.com and twitter.com, None of them that give a proper response, here's the approach:

import socket
import ssl

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
context = ssl.create_default_context()
context.set_ciphers(cipher)
sock.connect(('twitter.com', 443))
sock = context.wrap_socket(sock, server_hostname='twitter.com')
sock.sendall(bytes('GET h2://twitter.com/ HTTP/1.1\r\nHost: twitter.com\r\nConnection: Upgrade, HTTP2-Settings\r\nUpgrade: h2\r\nHTTP2-Settings: \r\nAlt-Svc: h2=":443"\r\n\r\n',encoding='utf-8'))

sock.settimeout(5)
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
line = str(sock.recv(10000))
print(line)

Upgrading the HTTP/1 connection to HTTP/2; giving 400 bad request, not what I'm expecting 101.

sock.connect(('www.google.com', 443))
sock = context.wrap_socket(sock, server_hostname='www.google.com')
sock.sendall(bytes('GET / HTTP/1.1\r\nHost: www.google.com\r\nConnection: Upgrade, HTTP2-Settings\r\nUpgrade: h2\r\nHTTP2-Settings: \r\n\r\n',encoding='utf-8'))

I've also tried to set ALPN protocol manually but google.com and twitter.com give different response:

context.set_alpn_protocols(['h2'])

for google.com there's frame response:

b'\x00\x00\x12\x04\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00d\x00\x04\x00\x10\x00\x00\x00\x06\x00\x01\x00\x00\x00\x00\x04\x08\x00\x00\x00\x00\x00\x00\x0f\x00\x01'

but twitter.com giving empty response frame:

b''

The reason for this is, i had to perform checks based on wordlist that contains list of website. How can i properly check if website supports for HTTP/2 in Python?

Attachment: Twitter

CodePudding user response:

yes, you do need to set the context.set_alpn_protocols(['h2']) and you can check if you successfully negotiated with sock.selected_alpn_protocol().

Unfortunately, if you want to actually test an http call, you need to encode the header (get, host, etc.). rfc7540 section 4 and section 6.2 detail the requirement. a python library like h2 can help with the encoding as well as properly encode and decode the other sadly necessary http2 chatter.

The whole connection upgrade thing is not used by web browsers, so it is not unexpected that websites don't support it. Once you have an alpn h2 negotiated tls stream, a properly encoded

GET / HTTP/2
Host: twitter.com

should be all you need. That is the reason twitter just closed the socket. I suspect the google frame sent back (if you used hpack to decode) would say something like "I don't understand".

  • Related