Repository navigation
fix(h2): 发送前把 header field name 规范化为小写(附 webapp HTTP/3 问题报告) - #63
Merged
Merged
Conversation
HTTP/2 的 field name 在线上必须全小写(RFC 9113 §8.2.1)。之前的 build_response_nv() / build_trailer_nv() / 请求头构建器直接拿原始名字 过 nghttp2_check_header_name():应用设置 `X-Mixed-Case` 这类 Header 时 返回 false,submit_* 返回 UV_EINVAL 且流不会发送,客户端只能等到超时。 uvscope 的 TLS h2 直连就是这样挂死的。 - 在 h2 响应/尾随头/请求头三条出口统一小写化,再校验、组帧 - 小写后的名字放在调用方的 name_store 里,保证 nghttp2_submit_* 期间 指针有效(不能放 builder 的局部变量) - web_ssl_app_h2_func 增加 /mixed-header 回归用例 验证:本地 1.8.2 构建 + 最小 webapp 用例,修复前混合大小写 Header 挂起, 修复后 HTTP/2 200;h3 的 webapp 响应问题另见 PR 描述。
`uvcpp_h2_session.cpp` 的组帧边界新增约 30 行(`lower_header_name` / `append_lower_header`),两条腿之后的引用整体后移。4 条都是同宽平移 (+19 / +23 / +27),没有歧义;锁文件按 `--update` 重刷。 - doc/http2-guide.md: 1216→1235、1322→1345 - doc/http2-status.md: 1210-1216→1229-1235、1691→1718
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
h2 修复(本 PR 已就绪)
HTTP/2 的 field name 在线上必须全小写(RFC 9113 §8.2.1)。之前
build_response_nv()/build_trailer_nv()/ 请求头构建器直接拿原始名字过nghttp2_check_header_name():应用设置X-Mixed-Case、Cache-Control这类混合大小写 Header 时返回 false,
submit_*返回UV_EINVAL,流停在“提交过、一个字节都没发”的状态,客户端只能等到超时。
最小复现(
uvcpp_web_app+ TLS + h2):改成
cache-control立即正常。修复:
name_store里(与store/nv同寿命),避免 builder 返回后
nghttp2_submit_*拿到悬垂指针;回归测试:
tests/functional/web_ssl_app_h2_func.cpp新增/mixed-header路由(设置
X-Mixed-Case),场景 1 请求它并断言 HTTP/2 200 +mixed-ok。修复前该用例超时,修复后通过。
本地验证:
也在 1.8.2 树上用最小 webapp 用例验证:混合大小写 Header 修复前挂起,修复后
HTTP/2 200。
webapp 的 HTTP/3 缺口(需要负责人跟进)
本 PR 没有修 h3;下面是完整复现、日志和根因,方便按同一分支继续。
复现
app.http_server()->set_quic_ssl_context(&quic_tls);app.http_server()->listen_quic(port, host);,然后app.start()。/api/health。现象
start()无条件安装http_->set_stream_claim(...);dispatch_h3_request()只要看到 claim hook 就拒绝整条 h3 请求:[uvcpp_http_server] h3 上不支持 set_stream_claim() 装的认领钩子 ...http_server()->clear_stream_claim()后,请求确实进了webapp 路由,但响应被丢弃:
h3 客户端 8 秒超时。此时底层 h3 本身是通的(同一服务端用 h3 客户端拿到过
HTTP/3 200,只是响应为空/默认)。根因
uvcpp_web_app::start()(src/webapp/uvcpp_web_app.cpp约 2049 行)无条件set_stream_claim,即使没有任何post_stream()流式路由。h3 派发器(
src/web/uvcpp_http_server.cpp约 3261 行refuse_claim)因此拒绝所有 h3请求。
uvcpp_web_app::on_http_request()(约 3441 行)把请求绑定到uvcpp_web_context/connection_id;响应最终走uvcpp_web_app::send_response(),里面reg_client(ctx.connection_id())在 h3上返回 nullptr(h3 没有 TCP client),于是日志“连接已断开,响应被丢弃”。
建议修法
post_stream()路由时安装 claim hook(或在 h3 上忽略它);client == nullptr)不要走 TCP 绑定的 context/send_response:resp交回dispatch_h3_request()的send_h3_response(),不要自己发;req.reply+send_reply()的 h3 deferred 路径;h3_header组帧路径也做同样的 field name 小写规范化(nghttp3同样要求小写)。
环境
uvcpp_http_server的 h3 用例/http3_web_func正常;问题在uvcpp_web_app这一层。