#headers —— 大小写不敏感的 HTTP 头集合

    纯逻辑包:字符串规范化与集合运算,不碰网络、不碰 async。对应 axios 的 AxiosHeaders。

    import { "q2316367743/moonhttp/headers", }

    #语义

    • 头名大小写不敏感(HTTP/1.1 规定只在 ASCII 范围内折叠,RFC 9110 §5.1):get("Content-Type") 与 get("content-type") 命中同一条。内部以小写名作 key,同时记住写入时的原始拼写用于输出(同一头名首次出现的拼写胜出)。
    • 所有变更方法都返回新实例,不做就地修改。Config 是值语义的,合并时同一份 Headers 可能被多个 Config 引用,返回新值才不会出现「改一个实例的头、另一个跟着变」。
    • 一个头名只有一个字符串值:不展开多值头。
    • 没有「用 false 表示这条头禁止被默认值覆盖」的哨兵值——库补默认头只用 set_if_absent。

    #API

    方法说明
    Headers::new()空集合
    Headers::from_pairs([("A", "1")])从数组构造
    Headers::get(name)取值,String?
    Headers::has(name)是否存在
    Headers::set(name, value)写入 / 覆盖,返回新实例
    Headers::set_if_absent(name, value)只在缺失时写入(补默认头用它)
    Headers::remove(name)删除,返回新实例
    Headers::merge(other)合并,other 的同名头覆盖本实例
    Headers::entries()全部 (名, 值),顺序即写入顺序
    Headers::length() / is_empty()数量判断
    Headers::to_string() / equal / not_equal / repr输出与比较(Show / Eq / Debug)

    #用法

    let headers = @headers.Headers::new()
    .set("Content-Type", "application/json")
    .set_if_absent("Accept", "application/json, text/plain, */*")

    headers.get("content-type") // Some("application/json")
    headers.has("ACCEPT") // true

    Headers

    pub struct Headers {
    // private fields
    }

    大小写不敏感的 HTTP 头集合,对应 axios 的 AxiosHeaders。

    内部以小写化后的头名作为 Map 的 key,值里再记住写入时的原始拼写, 于是 get("Content-Type") 与 get("content-type") 命中同一条记录, 而遍历/打印时仍然保留调用方书写时的形状(与 axios「首次出现的拼写胜出」一致)。

    与 axios 相比的两处有意简化(README 里有完整清单):
    • 不支持 axios 用 false 表示「这条头禁止被默认值覆盖」的哨兵值;
    • 同一个头名只能有一个字符串值,不展开多值头(axios 允许数组)。

    所有变更方法都返回新实例而不是就地修改:Config 是值语义的, 合并配置时同一份 Headers 可能被多个 Config 引用, 返回新值可以避免「改一个实例的头,另一个实例跟着变」这类共享可变状态 bug。
    impl Eq for Headers
    impl Show for Headers
    impl Debug for Headers

    Headers::entries

    fn Headers::entries(self : Headers) -> Array[(String, String)]

    展开为「头名, 值」数组,头名保留原始拼写,顺序为插入顺序。

    顺序有意义:请求级平铺的头是最后 merge 进来的, 因此它们在数组尾部,也是发送到网络上时最靠后的覆盖者。

    Headers::equal

    fn Headers::equal(self : Headers, other : Headers) -> Bool

    Headers::from_pairs

    fn Headers::from_pairs(pairs : Array[(String, String)]) -> Headers

    从「头名, 值」序列构造;同名(忽略大小写)时后出现的覆盖先出现的。

    Headers::get

    fn Headers::get(self : Headers, name : StringView) -> String?

    按名取值,大小写不敏感。查不到返回 None,而不是空串, 以便区分「这个头不存在」和「这个头的值是空字符串」。

    Headers::has

    fn Headers::has(self : Headers, name : StringView) -> Bool

    是否存在该头,大小写不敏感。

    Headers::is_empty

    fn Headers::is_empty(self : Headers) -> Bool

    是否一条头都没有。

    Headers::length

    fn Headers::length(self : Headers) -> Int

    头的条数。

    Headers::merge

    fn Headers::merge(self : Headers, other : Headers) -> Headers

    以 other 覆盖自身,返回新的集合(大小写不敏感,同名时 other 胜出)。

    这是 flatten_headers 实现「common 层 < 按方法层 < 请求级平铺」优先级的基石: 只要按优先级从低到高依次 merge,最终结果天然就是高优先级覆盖低优先级。

    Headers::new

    fn Headers::new() -> Headers

    空的头集合。

    Headers::not_equal

    fn Headers::not_equal(x : Headers, y : Headers) -> Bool

    Headers::output

    fn Headers::output(self : Headers, logger : &Logger) -> Unit

    显式声明把 Show 的方法挂成常规方法。 隐式挂载已被标记为废弃,这里按当前推荐写法显式 extend; to_string 不用列进来,因为上面已经有一个同名的固有方法。

    Headers::remove

    fn Headers::remove(self : Headers, name : StringView) -> Headers

    删除一条头,返回新的集合;不存在时原样返回。

    Headers::set

    fn Headers::set(self : Headers, name : StringView, value : String) -> Headers

    写入一条头,返回新的集合;已有同名头(忽略大小写)时会被整体覆盖。

    (spelling, value) 一起替换:拼写以最后一次写入为准, 这与 axios 的 AxiosHeaders::set 默认覆盖行为一致。

    Headers::set_if_absent

    fn Headers::set_if_absent(self : Headers, name : StringView, value : String) -> Headers

    仅当同名头(忽略大小写)尚不存在时写入,返回新的集合。

    用于「补默认值但不能盖掉用户显式设置」的场景,例如自动补 Content-Type。

    Headers::to_repr

    Headers::to_string

    fn Headers::to_string(self : Headers) -> String

    渲染为 名: 值 形式,多条之间用 ", " 连接。 只用于日志与断言,不参与任何协议编码。

    Source Files