当前位置:首页 > 文章列表 > Golang > Go教程 > Go cookiejar 怎样让测试客户端保持会话 Cookie

Go cookiejar 怎样让测试客户端保持会话 Cookie

来源:17golang原创 2026-11-15 23:43:13 0浏览 收藏

给测试用的 http.Client 设置非空 Jar,再让同一用户的请求复用这个客户端,就能自动接收响应里的 Cookie,并在匹配的后续请求中携带。我的选择是把“客户端与独立 Jar”作为一个测试用户的整体,而不是在每次请求中手工拼 Cookie。

官方文档:https://pkg.go.dev/net/http/cookiejar;客户端接口:https://pkg.go.dev/net/http#Client。

先把 Cookie 状态绑定到客户端

这里需要的能力是状态容器,不是浏览器窗口。Jar 保存 Cookie;http.Client 将它绑定到请求和响应。Jar 为空时,Client 不会自动记住服务器下发的 Cookie,只发送请求上显式设置的值。直接调用包级 http.Get 也不会自动使用你另建的客户端。

本例的六个对象分属三个边界:测试用户包含 Client、Jar;HTTP 数据包含 Set-Cookie、Cookie;测试服务包含 /session、/profile。接口负责串起它们,连接复用与会话存储则是两回事。

客户端Jar与会话Cookie的静态关系
结构图:测试用户持有客户端和Jar;两类HTTP头与服务接口对应,连线表示静态关联。

用一个完整测试表达会话约定

将下面代码保存为已有 Go 模块中的 session_test.go,并将 golang.org/x/net/publicsuffix 加入模块依赖;依赖版本应与项目工具链要求相容。它属于 golang.org/x/net 模块,不是标准库包。此处给出可复用的测试写法,不附本机运行记录。

package session_test

import (
    "io"
    "net/http"
    "net/http/cookiejar"
    "net/http/httptest"
    "testing"
    "time"

    "golang.org/x/net/publicsuffix"
)

func TestClientKeepsSession(t *testing.T) {
    mux := http.NewServeMux()
    mux.HandleFunc("/session", func(w http.ResponseWriter, r *http.Request) {
        // 只提供测试会话标记,不代表真实认证或密码校验。
        if r.Method != http.MethodPost {
            w.WriteHeader(http.StatusMethodNotAllowed)
            return
        }
        http.SetCookie(w, &http.Cookie{
            Name: "session", Value: "test-user",
            Path: "/", HttpOnly: true,
        })
        w.WriteHeader(http.StatusNoContent)
    })
    mux.HandleFunc("/profile", func(w http.ResponseWriter, r *http.Request) {
        // 后续请求必须携带预期标记,才能通过测试约定。
        c, err := r.Cookie("session")
        if err != nil || c.Value != "test-user" {
            w.WriteHeader(http.StatusUnauthorized)
            return
        }
        w.WriteHeader(http.StatusNoContent)
    })
    server := httptest.NewServer(mux)
    t.Cleanup(server.Close)

    jar, err := cookiejar.New(&cookiejar.Options{
        PublicSuffixList: publicsuffix.List,
    })
    if err != nil {
        t.Fatal(err)
    }
    client := &http.Client{Jar: jar, Timeout: 3 * time.Second}
    t.Cleanup(client.CloseIdleConnections)

    // 读取并关闭每个响应体;不要把 defer 堆积在请求循环里。
    requestStatus := func(method, path string) int {
        t.Helper()
        req, err := http.NewRequest(method, server.URL+path, nil)
        if err != nil {
            t.Fatal(err)
        }
        resp, err := client.Do(req)
        if err != nil {
            t.Fatal(err)
        }
        _, readErr := io.Copy(io.Discard, resp.Body)
        closeErr := resp.Body.Close()
        if readErr != nil {
            t.Fatal(readErr)
        }
        if closeErr != nil {
            t.Fatal(closeErr)
        }
        return resp.StatusCode
    }
    if got := requestStatus(http.MethodGet, "/profile"); got != http.StatusUnauthorized {
        t.Fatalf("会话建立前状态码=%d", got)
    }
    if got := requestStatus(http.MethodPost, "/session"); got != http.StatusNoContent {
        t.Fatalf("设置会话状态码=%d", got)
    }
    if got := requestStatus(http.MethodGet, "/profile"); got != http.StatusNoContent {
        t.Fatalf("保持会话后状态码=%d", got)
    }
}

测试约定是:没有会话时访问资料接口得到401;POST建立标记得到204;再次访问资料接口得到204。这里刻意不手工复制响应 Cookie,才能让最后一个断言覆盖 Jar 与 Client 的绑定。若每次请求都新建 Jar,最后的请求没有此前的状态。

测试服务使用普通 HTTP,因此示例没有设置 Secure;这只是隔离测试的传输选择。它的固定值也只用于说明客户端保存能力,不能拿来充当实际用户凭据。

公共后缀列表决定域名边界

cookiejar.New(nil) 可以创建 Jar,但没有公共后缀保护。需要接触真实域名的客户端,我会显式传入 publicsuffix.List。官方包地址:https://pkg.go.dev/golang.org/x/net/publicsuffix。

公共后缀不等于简单取最后一个域名片段:例如 co.uk 本身就是公共后缀。列表帮助 Jar 约束服务器能设置的域范围;它不负责登录、不替应用授权,也不自动让任意子域共享会话。该包提供编译进依赖版本的数据快照,更新依赖才会更新快照。

从配置角度看,三个边界是“创建配置”(Options、PublicSuffixList)、“规则依赖”(publicsuffix.List、公共后缀数据)、“状态容器”(Jar、Domain)。Options 关联 PublicSuffixList 和 Jar,PublicSuffixList 关联实现,实现关联数据;Jar 对 Domain 的处理受这些规则约束。

公共后缀配置与Jar域名策略依赖
结构图:公共后缀列表是Jar的域名策略依赖,不是用户认证或域名共享开关。

保持会话时容易忽略的限制

现象优先检查调整方向
设置接口成功,后续仍是401是否复用了同一Jar让同一测试用户复用带Jar的Client
换路径就没有CookieCookie的Path范围按接口实际范围设置;示例明确使用/
换主机名后丢失会话实际URL主机与Domain不要混用localhost和127.0.0.1
不同用户相互影响是否共享了Jar每个用户分别创建Jar
HTTP请求不带Secure CookieURL协议需要该属性的测试使用HTTPS服务

共享连接池不等于共享用户身份;Cookie 也不按端口隔离,因此给两个测试服务分配不同端口,不足以保证共享 Jar 时的用户隔离。对于重定向,Client 会为它跟随的每个目标咨询 Jar;不能把一次登录理解为对所有目标都发送同一份头。

这套内存 Jar 不会自动保存到磁盘,也不是完整浏览器环境。若需求是浏览器脚本、跨站上下文或页面策略行为,应在对应浏览器环境中另外测试。本文只覆盖 HTTP 客户端会话 Cookie。

常见问题

只调用 Request.AddCookie 可以吗?

可以给单次请求添加值,但服务器更新 Cookie 后,手工方式还要自行同步。要表达连续会话,我更愿意把状态交给 Jar。

HttpOnly 会阻止Go客户端发送Cookie吗?

不会。它主要限制浏览器脚本访问,不能用来解释这里的请求为何缺少Cookie。

同一个客户端适合多个测试用户吗?

同一Jar意味着共享会话容器。需要独立身份时,创建各自的Client与Jar;可以根据测试设计另行考虑底层Transport的复用。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Go cmplx.Rect 怎样把幅值和相位转换成复数Go cmplx.Rect 怎样把幅值和相位转换成复数
上一篇
Go cmplx.Rect 怎样把幅值和相位转换成复数
Go cmplx.Conj 怎样计算复数的共轭值
下一篇
Go cmplx.Conj 怎样计算复数的共轭值
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    1043次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    1041次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    1195次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    1143次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    989次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码