关于 fit-framework HTTP 中 Header 处理的优化
@CodeCasterX 已经在做这个了。
开始于 2025年9月30日。
评估
这个 Issue 还没有评估数据。
描述
功能摘要 / Feature Summary
优化fit-framework中的Header设计
功能类型 / Feature Type
全新功能 / New Feature
优先级 / Priority
高 - 非常需要这个功能 / High - Really need this feature
问题描述 / Problem Description
关于fit-framework当前的Header逻辑
modelengine.fit.http.header.HeaderValue
public interface HeaderValue {
/**
* 获取消息头的值。
*
* @return 表示消息头值的 {@link String}。
*/
String value();
/**
* 获取所有参数集合。
*
* @return 表示所有参数集合的 {@link ParameterCollection}。
*/
ParameterCollection parameters();
当前的Header值类例如 ContentType 都继承于 HeaderValue ,HeaderValue统一了一套基于value+parameters的模式,是由于例如Content-Type、Content-Disposition、Accept 等都在各自的RFC中定义了这一套格式。
但是在[RFC 9110]§5.5中定义field-value:
field-value = *field-content
field-content = field-vchar
[ 1*( SP / HTAB / field-vchar ) field-vchar ]
field-vchar = VCHAR / obs-text
obs-text = %x80-FF
仅定义了字符要求,并没有严格统一的格式。各自Header的格式都在自己的规范中定义。
例如 User-Agent 的 [RFC7321]中说明:
User-Agent = product *( RWS ( product / comment ) )
product = token ["/" product-version]
product-version = token
允许以下的值
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ...
使得当前的Header中固定要求的value+parameters模式很难统一和继承。
建议的解决方案 / Proposed Solution
Spring HttpHeaders + Tomcat中的设计
Spring是依赖于servlet的设计,因此许多关于Header的解析代码都依赖于servlet容器。
servlet标准要求容器提供了以下的接口方法:
public interface HttpServletRequest extends ServletRequest {
String BASIC_AUTH = "BASIC";
String FORM_AUTH = "FORM";
String CLIENT_CERT_AUTH = "CLIENT_CERT";
String DIGEST_AUTH = "DIGEST";
String getAuthType();
Cookie[] getCookies();
long getDateHeader(String var1);
String getHeader(String var1);
Enumeration<String> getHeaders(String var1);
Enumeration<String> getHeaderNames();
int getIntHeader(String var1);
}
Tomcat的行为
Tomcat会对接收到的Header进行 field-name : field-value 依照[RFC 9110]
将得到的数据放入 MimeHeaders 类似于 Map<header-key, header-value>。
然后Tomcat会对自己的例如Host,Connection,Content-Length,Transfer-Encoding,Expect等协议层必须依赖的header字段进行解析,剩余的header字段仅保存字节流。
其他的Header主要采用懒加载的方式,在相应的getHeader触发的时候,进行解析成上层类并进行缓存处理,后续调用返回缓存。
Spring的行为
Spring又自行定义了许多上层类。
HttpHeaders implements MultiValueMap<String, String>
然后分别写 getter,setter针对每个Header进行单独序列化和反序列化。(下为片段
org.springframework.http.HttpHeaders )
public void setAccept(List<MediaType> acceptableMediaTypes) {
this.set("Accept", MediaType.toString(acceptableMediaTypes));
}
public List<MediaType> getAccept() {
return MediaType.parseMediaTypes(this.get("Accept"));
}
public void setAcceptLanguage(List<Locale.LanguageRange> languages) {
Assert.notNull(languages, "LanguageRange List must not be null");
DecimalFormat decimal = new DecimalFormat("0.0", DECIMAL_FORMAT_SYMBOLS);
List<String> values = languages.stream().map((range) -> range.getWeight() == (double)1.0F ? range.getRange() : range.getRange() + ";q=" + decimal.format(range.getWeight())).toList();
this.set("Accept-Language", this.toCommaDelimitedString(values));
}
public List<Locale.LanguageRange> getAcceptLanguage() {
String value = this.getFirst("Accept-Language");
return StringUtils.hasText(value) ? LanguageRange.parse(value) : Collections.emptyList();
}
public void setAcceptLanguageAsLocales(List<Locale> locales) {
this.setAcceptLanguage(locales.stream().map((locale) -> new Locale.LanguageRange(locale.toLanguageTag())).toList());
}
public List<Locale> getAcceptLanguageAsLocales() {
List<Locale.LanguageRange> ranges = this.getAcceptLanguage();
return ranges.isEmpty() ? Collections.emptyList() : ranges.stream().map((range) -> Locale.forLanguageTag(range.getRange())).filter((locale) -> StringUtils.hasText(locale.getDisplayName())).toList();
}
Spring 的 HttpHeaders 是依赖 servlet 提供的原始 Header 数据,但完全独立于底层的解析逻辑。
修改方案:
是否可以参考 Spring 的做法:底层统一存 String,按需解析到上层对象,而不是在 HeaderValue 接口里强行统一格式。
替代方案 / Alternative Solutions
No response
确认事项 / Confirmations
-
我已经搜索了现有的 issues 和讨论,确认这不是重复建议
I have searched existing issues and discussions, confirming this is not a duplicate suggestion -
这个功能符合项目的目标和范围
This feature aligns with the project's goals and scope -
我理解这个功能可能需要时间来实现
I understand this feature may take time to implement -
我愿意协助实现这个功能 (可选)
I'm willing to help implement this feature (optional)
- 主要语言
- Java
- 星标
- 2.1k
- 派生
- 335
- PR 合并指标
- 30 天内没有已合并 PR
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
ModelEngine-Group/fit-framework 的其他 Issue
-
难度 4/5 3-5 天 新手友好度 48/100
-
Emitter支持onTimeout回调可能重新可做 @CodeCasterX 于 351 天前认领,目前没有进行中的 PR。 未关闭status: waiting-for-internal-feedback type: feature
ModelEngine-Group/fit-framework#356 · 已指派 1 人 ·
-
MCP协议method命名格式需要统一可能重新可做 @CodeCasterX 于 392 天前认领,目前没有进行中的 PR。 未关闭status: waiting-for-internal-feedback type: feature
ModelEngine-Group/fit-framework#298 · 已指派 1 人 ·
-
tool-maven-plugin插件解析runnables兼容Fitable、Genericable中的id属性可能重新可做 @CodeCasterX 于 404 天前认领,目前没有进行中的 PR。 未关闭status: waiting-for-triage type: bug
ModelEngine-Group/fit-framework#286 · 已指派 1 人 ·
-
feat(fit): Nacos 注册中心支持 HTTPS 双向认证可能重新可做 @CodeCasterX 于 404 天前认领,目前没有进行中的 PR。 未关闭status: waiting-for-internal-feedback type: feature
ModelEngine-Group/fit-framework#284 · 2 条评论 · 已指派 1 人 ·
查看 ModelEngine-Group/fit-framework 的全部 Issue
相似的 Issue
-
难度 2/5 1-3 小时 新手友好度 72/100
维护者通常 1 天内回复
-
bug new windows
难度 2/5 1-3 小时 新手友好度 62/100
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 75/100
GantMan/jail-monkey#380 ·
-
难度 2/5 1-3 小时 新手友好度 72/100
objectionary/jucs#145 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 82/100
objectionary/lints#1559 ·
维护者通常 2 天内回复