Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

关于 fit-framework HTTP 中 Header 处理的优化

未关闭
#329 2 条评论 0 个 reaction 已指派 1 人 在 GitHub 查看

@CodeCasterX 已经在做这个了。

开始于 2025年9月30日。

评估

这个 Issue 还没有评估数据。

描述

type: enhancement
功能摘要 / 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

环境准备

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

ModelEngine-Group/fit-framework 的其他 Issue

查看 ModelEngine-Group/fit-framework 的全部 Issue

相似的 Issue

更多 Java Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。