Conversation
…ions Extract url preparation, media type resolution, params encoding, request body building and option applying into dedicated helpers, so each step can be read and tested independently. The url protocol completion is also fixed: the previous check of "url contains http" missed urls with "http" inside the host (eg. "myhttpservice.com") and mangled urls with non-http schemes. It is now scheme detection anchored at the beginning of the url.
This branch has not been deployed
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.
背景
net/gclient的prepareRequest是每个请求都要走的"组装请求"函数:从拼 URL 到最终发出请求前的所有准备都在这一个函数里,212 行、约 30 个判断点、最深 5 层嵌套。它同时负责五件事:http://协议头@file:)、普通 body带来的现实问题:难读,难改
改动
一、拆解(对行为零影响)
prepareRequest收缩为 27 行的编排(先编码参数 → 按三种形态装配请求 → 注入选项),拆出 8 个私有辅助函数,全部留在原文件net/gclient/gclient_request.go:prepareRequestURLresolveRequestMediaTypeencodeRequestParamsnewGetRequestnewMultipartRequestwriteMultipartItemk=v项写入(含@file:上传判定)newNormalRequestapplyRequestOptions顺带消掉的重复与噪音:Content-Type 二次解析与重复兜底、
err遮蔽、5 层嵌套(现在最深 3 层)。二、修复:URL 协议判断
拆解过程中发现 URL 协议判断有一处 bug(域名含
http子串会漏拼协议头)。原来的判据是"URL 整串里出现过http字样",既不是"有没有协议头",也不是"协议头是不是 http",因此漏拼甚至拼坏三类输入,一并修复:myhttpservice.com/api(域名含http子串)unsupported protocol scheme ""http://myhttpservice.com/apiexample.com/a?u=http://b(查询串含http)http://example.com/a?u=http://bftp://x.com/a(非 http 协议)http://ftp://x.com/a,实际去连主机名ftp(静默打错主机)unsupported protocol scheme "ftp"新判据:
^[a-zA-Z][a-zA-Z0-9+.-]*://(锚定开头、且要求带://)。为什么不直接
url.Parse后看Scheme:localhost:8000会被解析成Scheme=localhost、127.0.0.1:8000会直接解析报错,两种都要额外兜底才能救回来;而"必须带://"让host:port天然不匹配,不需要任何特判。兼容性
prepareRequest是私有方法、唯一调用点是DoRequest,无公开 API 变化;错误消息文本、各步骤执行顺序(header 注入在自动探测之后、Cookie 在 Host 之后等)、GET 无参数也构造空 body 等细节全部原样保留。http://x、HTTP://X、localhost:8000、127.0.0.1:8000、带 prefix 的相对路径等)修复前后完全一致。测试
net/gclient/gclient_z_unit_internal_test.go:Test_PrepareRequestURL:14 条 table 用例,钉住上表全部输入 + 大小写协议头 + 空串 + prefix 组合(含 trim);Test_PrepareRequest_SchemeCompleted:走完整prepareRequest,断言req.URL的 Scheme / Host / Path。go test ./net/gclient/ ./internal/httputil/全绿(gclient 约 30s,覆盖文件上传、特殊字符参数、JSON body 含@file:不触发上传、表单字段截断等边界用例);net/ghttp定向(Test_Params_File*9 个、Test_Params_Struct*3 个、Test_Client*)通过。gofmt干净,golangci-lint对改动文件无告警。复现