如何在Python中检测网站是否支持HTTP/2协议
如何在Python中批量检测网站是否支持HTTP/2?
问题背景
我尝试通过Socket将HTTP/1连接升级为HTTP/2以获取101 Switching Protocol响应,测试了google.com、twitter.com这类支持HTTP/2的大型网站,但未得到预期结果:使用升级请求返回400错误;手动设置ALPN协议['h2']后,google.com返回帧响应,twitter.com返回空帧。现在需要基于网站列表(wordlist)批量检测,请问如何在Python中正确检测网站是否支持HTTP/2?
你的尝试代码
针对twitter.com的请求代码
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)
针对google.com的请求代码
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'))
设置ALPN的代码片段
context.set_alpn_protocols(['h2'])
正确的批量检测方案
HTTP/2的主流启用方式是通过ALPN协议协商(而非HTTP/1升级),绝大多数现代网站只支持ALPN方式的HTTP/2,不支持HTTP/1升级(这就是你用Upgrade请求返回400的原因)。因此正确的检测方式是在SSL握手阶段设置ALPN列表,然后检查协商结果。
以下是可批量检测的Python代码:
import socket import ssl from concurrent.futures import ThreadPoolExecutor def check_http2_support(host): result = {"host": host, "supports_http2": False, "error": None} try: # 创建TCP socket sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(10) # 连接443端口 sock.connect((host, 443)) # 创建SSL上下文,设置ALPN协议列表(h2是HTTP/2的标识) context = ssl.create_default_context() context.set_alpn_protocols(['h2', 'http/1.1']) # 握手并获取协商的协议 with context.wrap_socket(sock, server_hostname=host) as ssock: negotiated_protocol = ssock.selected_alpn_protocol() if negotiated_protocol == 'h2': result["supports_http2"] = True except Exception as e: result["error"] = str(e) finally: sock.close() return result def batch_check(wordlist_path, max_workers=10): # 读取网站列表 with open(wordlist_path, 'r', encoding='utf-8') as f: hosts = [line.strip() for line in f if line.strip()] # 多线程批量检测 with ThreadPoolExecutor(max_workers=max_workers) as executor: results = list(executor.map(check_http2_support, hosts)) # 输出结果 for res in results: status = "支持" if res["supports_http2"] else "不支持" error_msg = f" | 错误: {res['error']}" if res["error"] else "" print(f"{res['host']}: {status} HTTP/2 {error_msg}") # 示例调用 if __name__ == "__main__": batch_check("website_list.txt")
关键说明
- ALPN协商是标准方式:HTTP/2的官方推荐启用方式是TLS握手时通过ALPN协商,绝大多数网站(包括Google、Twitter)只支持这种方式,不支持HTTP/1升级请求。
- 多线程提升效率:批量检测时用多线程可以大幅缩短总耗时,避免单线程等待超时的低效问题。
- 错误处理:代码包含超时、连接失败等异常处理,确保批量检测不会因单个网站故障中断。
内容的提问来源于stack exchange,提问作者user19219732
相关产品推荐
相关产品推荐

