Firefox接收Kvarn Web服务器HTTP/2推送时无响应问题求助
我正在开发一款名为Kvarn的Web服务器,它支持HTTP/2协议,我计划将其打造为HTTP Push领域的领先实现。
目前该服务器已托管了kvarn.org和icelk.dev两个站点,你可以自行访问测试。
发送推送请求的相关代码可查看此处。
最近我遇到了一个问题:我实现的推送功能在Firefox上无法正常工作,看起来推送的资源流没有正常关闭,Firefox开发者工具显示对应资源尚未收到服务器返回的首字节。
我的技术栈为Rust + Tokio,使用H2库实现HTTP/2协议。
该功能在Chromium系浏览器和Safari上完全正常,我记得在早前几个版本的Firefox上也能正常运行,我用Tor Browser测试也能正常工作,这点十分奇怪,因为Tor Browser是基于Firefox构建的。
我找到了另一款支持HTTP Push的站点,是Go语言团队提供的测试站点,它在Firefox上可以正常使用HTTP/2推送功能。
之后我使用nghttp工具对Kvarn进行了测试,测试结果如下:
[ERROR] Could not connect to the address ::1 Trying next address 127.0.0.1 [ 0.013] Connected [WARNING] Certificate verification failed: Hostname mismatch The negotiated protocol: h2 [ 0.035] send SETTINGS frame <length=12, flags=0x00, stream_id=0> (niv=2) [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100] [SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535] [ 0.035] send PRIORITY frame <length=5, flags=0x00, stream_id=3> (dep_stream_id=0, weight=201, exclusive=0) [ 0.035] send PRIORITY frame <length=5, flags=0x00, stream_id=5> (dep_stream_id=0, weight=101, exclusive=0) [ 0.035] send PRIORITY frame <length=5, flags=0x00, stream_id=7> (dep_stream_id=0, weight=1, exclusive=0) [ 0.035] send PRIORITY frame <length=5, flags=0x00, stream_id=9> (dep_stream_id=7, weight=1, exclusive=0) [ 0.035] send PRIORITY frame <length=5, flags=0x00, stream_id=11> (dep_stream_id=3, weight=1, exclusive=0) [ 0.035] send HEADERS frame <length=38, flags=0x25, stream_id=13> ; END_STREAM | END_HEADERS | PRIORITY (padlen=0, dep_stream_id=11, weight=16, exclusive=0) ; Open new stream :method: GET :path: / :scheme: https :authority: localhost:8443 accept: */* accept-encoding: gzip, deflate user-agent: nghttp2/1.43.0 [ 0.040] recv SETTINGS frame <length=0, flags=0x00, stream_id=0> (niv=0) [ 0.040] send SETTINGS frame <length=0, flags=0x01, stream_id=0> ; ACK (niv=0) [ 0.043] recv SETTINGS frame <length=0, flags=0x01, stream_id=0> ; ACK (niv=0) [ 0.072] recv (stream_id=13) :status: 200 [ 0.072] recv (stream_id=13) cache-control: no-store [ 0.072] recv (stream_id=13) server: Kvarn/0.2.0 (macOS) [ 0.072] recv (stream_id=13) content-type: text/html; charset=utf-8 [ 0.072] recv (stream_id=13) content-encoding: gzip [ 0.072] recv (stream_id=13) accept-ranges: bytes [ 0.072] recv (stream_id=13) referrer-policy: no-referrer [ 0.073] recv HEADERS frame <length=79, flags=0x04, stream_id=13> ; END_HEADERS (padlen=0) ; First response header [ 0.073] recv DATA frame <length=2349, flags=0x00, stream_id=13> [ 0.073] recv (stream_id=13) :method: GET [ 0.073] recv (stream_id=13) :scheme: https [ 0.073] recv (stream_id=13) :authority: localhost:8443 [ 0.073] recv (stream_id=13) :path: /theme.css [ 0.073] recv (stream_id=13) accept-encoding: gzip, deflate [ 0.073] recv PUSH_PROMISE frame <length=28, flags=0x04, stream_id=13> ; END_HEADERS (padlen=0, promised_stream_id=2) [ 0.073] recv (stream_id=2) :status: 200 [ 0.073] recv (stream_id=2) cache-control: no-store [ 0.073] recv (stream_id=2) server: Kvarn/0.2.0 (macOS) [ 0.073] recv (stream_id=2) content-type: text/css; charset=utf-8 [ 0.073] recv (stream_id=2) content-encoding: gzip [ 0.073] recv (stream_id=2) accept-ranges: bytes [ 0.073] recv (stream_id=2) referrer-policy: no-referrer [ 0.073] recv HEADERS frame <length=25, flags=0x04, stream_id=2> ; END_HEADERS (padlen=0) ; First push response header [ 0.073] recv (stream_id=13) :method: GET [ 0.073] recv (stream_id=13) :scheme: https [ 0.073] recv (stream_id=13) :authority: localhost:8443 [ 0.073] recv (stream_id=13) :path: /style.css [ 0.073] recv (stream_id=13) accept-encoding: gzip, deflate [ 0.073] recv PUSH_PROMISE frame <length=17, flags=0x04, stream_id=13> ; END_HEADERS (padlen=0, promised_stream_id=4) [ 0.073] recv DATA frame <length=506, flags=0x01, stream_id=2> ; END_STREAM [ 0.073] recv (stream_id=4) :status: 200 [ 0.073] recv (stream_id=4) cache-control: no-store [ 0.073] recv (stream_id=4) server: Kvarn/0.2.0 (macOS) [ 0.073] recv (stream_id=4) content-type: text/css; charset=utf-8 [ 0.073] recv (stream_id=4) content-encoding: gzip [ 0.073] recv (stream_id=4) accept-ranges: bytes [ 0.073] recv (stream_id=4) referrer-policy: no-referrer [ 0.073] recv HEADERS frame <length=7, flags=0x04, stream_id=4> ; END_HEADERS (padlen=0) ; First push response header [ 0.073] recv (stream_id=13) :method: GET [ 0.073] recv (stream_id=13) :scheme: https [ 0.073] recv (stream_id=13) :authority: localhost:8443 [ 0.073] recv (stream_id=13) :path: /script.js [ 0.073] recv (stream_id=13) accept-encoding: gzip, deflate [ 0.073] recv PUSH_PROMISE frame <length=17, flags=0x04, stream_id=13> ; END_HEADERS (padlen=0, promised_stream_id=6) [ 0.073] recv DATA frame <length=2323, flags=0x01, stream_id=4> ; END_STREAM [ 0.073] recv (stream_id=6) :status: 200 [ 0.073] recv (stream_id=6) cache-control: no-store [ 0.073] recv (stream_id=6) server: Kvarn/0.2.0 (macOS) [ 0.073] recv (stream_id=6) content-type: application/javascript; charset=utf-8 [ 0.073] recv (stream_id=6) content-encoding: gzip [ 0.073] recv (stream_id=6) accept-ranges: bytes [ 0.073] recv (stream_id=6) referrer-policy: no-referrer [ 0.073] recv HEADERS frame <length=34, flags=0x04, stream_id=6> ; END_HEADERS (padlen=0) ; First push response header [ 0.073] recv DATA frame <length=0, flags=0x01, stream_id=13> ; END_STREAM [ 0.073] recv DATA frame <length=1717, flags=0x01, stream_id=6> ; END_STREAM [ 0.074] send GOAWAY frame <length=8, flags=0x00, stream_id=0> (last_stream_id=6, error_code=NO_ERROR(0x00), opaque_data(0)=[])
测试日志看起来没有问题,和Go示例站点的同场景测试返回的数据帧结构完全一致。
之前我提到看起来像是流没有关闭,我也做了验证:在我认为流已经关闭后尝试再次向流写入数据,确实触发了H2库的报错,说明流已经正常关闭。
最后我还使用h2spec工具对实现进行了测试,所有测试项全部通过,而Go的示例站点并没有全部通过测试。
我现在已经找不到可能的问题点了,提前感谢大家提供的任何帮助,非常感激。
内容的提问来源于stack exchange,提问作者Icelk
相关产品推荐
相关产品推荐

