恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
CC Switch本地代理原理与Codex编程闭环实战指南
首页
资讯中心
/
CC Switch本地代理原理与Codex编程闭环实战指南
CC Switch本地代理原理与Codex编程闭环实战指南
发布时间:2026/9/10 2:45:05
1. 项目概述CC Switch 与 Codex 的协同本质不是“插件关系”而是本地智能代理架构的落地实践CC Switch 是什么它不是传统意义上的浏览器插件也不是一个独立运行的 AI 应用程序而是一个运行在你本地电脑上的轻量级反向代理服务。它的核心身份是“中间人”——当你在 Codex一款面向开发者的本地 AI 编程助手中发起一次代码补全、解释或重构请求时这个请求并不会直接飞向某个云服务商的 API 端点而是先被 CC Switch 拦截、解析、重写再根据你的配置转发给 DeepSeek、Qwen、GLM、Claude Desktop 或 Ollama 托管的本地模型。你可以把它理解成你电脑里一个懂协议、会翻译、能路由的“AI交通调度员”。它不生成内容但决定了内容从哪来、怎么来、以什么格式回来。Codex 则是另一个维度的存在。它不是一个大模型而是一个高度可定制的本地 AI 编程工作台。它本身不内置大模型也不依赖某一家云厂商。它的价值在于提供了一个结构清晰、响应极快、深度集成 IDE如 VS Code的前端界面和执行环境。Codex 负责理解你在编辑器里光标的位置、当前文件的语言、选中的代码片段并将这些上下文组织成标准的 OpenAI 兼容格式/v1/chat/completions然后发出去。它像一个经验丰富的“作战指挥官”清楚要打什么仗、带什么兵但具体开枪的士兵得由 CC Switch 去前线调遣。所以“CC Switch 怎么搭配 Codex 使用”这个问题本质上是在问如何在我自己的电脑上搭建一套“指挥官Codex 调度中心CC Switch 多兵种部队DeepSeek/Qwen/GLM/Ollama”的完整本地 AI 编程闭环。这完全绕开了任何需要登录、订阅、网络验证的云端服务所有数据、所有推理、所有日志都只存在于你自己的硬盘和内存里。这也是为什么大量开发者在搜索cc switch local proxy failed while handling codex endpoint /responses这类报错时焦虑的根源往往不是软件坏了而是这个“调度中心”的配置没对上“指挥官”的指令格式或者“部队”根本没列队报到。我第一次把 Codex 和 CC Switch 配通时是在一个没有外网的客户内网环境里。客户明确要求所有代码分析必须离线且不能有任何外部 API 调用。当时试了三个方案直接让 Codex 接 Ollama太慢响应延迟超过 8 秒、用 ngrok 反向代理到公网模型违反安全策略、最后才想到用 CC Switch 做本地协议桥接。实测下来整个链路稳定度远超预期而且因为所有流量都在 localhost:3000 和 localhost:11434 之间流转连防火墙规则都不用动。这种“本地即服务”的架构才是它在开发者圈子里快速出圈的真实原因——它解决的从来不是“能不能用”而是“敢不敢用、安不安心用”。2. 核心设计逻辑为什么必须用 CC Switch 做中间层Codex 无法直连第三方模型的底层限制Codex 的设计哲学是“协议至上”它默认只认 OpenAI 的 RESTful API 标准。这意味着无论你后端跑的是 DeepSeek-VL、Qwen2.5-Coder 还是 GLM-5-FlashCodex 都期望收到一个符合以下结构的 JSON 响应{ id: chatcmpl-xxx, object: chat.completion, created: 1717123456, model: gpt-4o-mini, choices: [{ index: 0, message: { role: assistant, content: 这是模型返回的纯文本答案 }, finish_reason: stop }] }但现实是残酷的。DeepSeek 官方 API 返回的字段叫response而不是choices[0].message.contentQwen 的流式响应里delta字段嵌套在choices[0].delta.content下而 DeepSeek 的流式却是choices[0].delta.response更麻烦的是GLM-5 的 thinking mode思维链模式强制要求你在请求体里带上reasoning_content字段否则直接返回 HTTP 400 错误——而 Codex 的原始请求体里压根没有这个字段。这就是你看到the reasoning_content in the thinking mode must be passed back to the api.这个报错的根源不是模型挂了是 Codex 发出的“作战指令”格式根本没通过 CC Switch 这个“军令翻译官”的校验。CC Switch 的核心价值就体现在它对这些“方言”的实时翻译能力上。它不是简单地做 URL 转发而是在请求发出前Request Interception和响应返回后Response Rewriting两个关键节点插入自定义的 JavaScript 脚本。比如当 Codex 向http://localhost:3000/v1/chat/completions发起请求时CC Switch 会解析请求头与 Body检查Authorization是否为Bearer xxx提取model参数值如deepseek-v4-flash动态重写请求目标将原请求转发至http://localhost:11434/api/chatOllama或http://127.0.0.1:8000/v1/chat/completionsDeepSeek 自建服务注入缺失字段若目标模型是 GLM-5 且启用了 thinking mode自动在请求体中添加reasoning_content: true标准化响应体将 Ollama 的message.content、DeepSeek 的response、Qwen 的choices[0].delta.content统一映射回 OpenAI 标准的choices[0].message.content结构。这个过程就是为什么你不能跳过 CC Switch直接让 Codex 指向http://localhost:8000的原因。Codex 不是通用 HTTP 客户端它是一个“协议洁癖者”。我曾试过用 curl 模拟 Codex 请求去调 DeepSeek 服务手动补全所有字段花了整整两天才把流式响应的 chunk 解析逻辑对齐。而 CC Switch 把这套复杂逻辑封装成了一个配置项你只需要在config.yaml里写一行model_mapping: { codex-deepseek: deepseek-v4-flash }剩下的全部交给它。提示很多初学者卡在unexpected status 404 not found90% 的情况是 CC Switch 的upstream_url配错了。它不是填 Codex 的地址而是填你实际部署的模型服务地址。例如如果你用ollama run qwen2.5-coder启动了 Qwen那 upstream_url 就是http://127.0.0.1:11434如果你用fastapivLLM部署了 DeepSeek那 upstream_url 就是http://127.0.0.1:8000。填反了CC Switch 就会向一个不存在的服务发请求自然 404。3. 实操配置详解从零开始搭建 Codex CC Switch DeepSeek 本地编程闭环含 Windows/macOS 双平台适配3.1 环境准备与工具链安装拒绝“一键安装包”亲手掌控每个环节在开始配置前请务必放弃“下载一个 exe 就完事”的幻想。CC Switch 和 Codex 的稳定性极度依赖底层环境的干净与可控。我建议采用以下分步安装法全程使用命令行确保每一步都可追溯、可复现。第一步安装 Node.jsCC Switch 运行基础CC Switch 是基于 Node.js 开发的因此必须先安装 Node.js。不要用 nvm-windows 或 Homebrew 直接装最新版因为某些 v20 版本与 CC Switch 的 crypto 模块存在兼容性问题。我的实测推荐版本是Node.js v18.20.4 LTS2023 年 10 月发布的长期支持版。Windows 用户前往 https://nodejs.org/dist/v18.20.4/ 下载node-v18.20.4-x64.msi安装时勾选 “Add to PATH”macOS 用户使用 Homebrew 安装brew install node18然后执行echo export PATH/opt/homebrew/opt/node18/bin:$PATH ~/.zshrc source ~/.zshrc。验证安装打开终端输入node -v应输出v18.20.4输入npm -v应输出9.6.7或相近版本。第二步安装 Codex选择 CLI 版本避开桌面版闪退陷阱Codex 官方提供了 CLI命令行界面和 Desktop桌面应用两个版本。大量用户反馈cc switch 开启后自己闪退根本原因在于 Codex Desktop 在 Windows 上会尝试 hook 系统级 UI 组件与某些显卡驱动或杀毒软件冲突。而 CLI 版本则完全规避了这个问题且启动速度更快、资源占用更低。全局安装 Codex CLInpm install -g codex-ai/codex-cli初始化配置目录codex init它会在~/.codexmacOS/Linux或%USERPROFILE%\.codexWindows下创建初始配置。验证codex --version应输出类似v0.12.3的版本号。第三步部署后端模型服务以 DeepSeek-V4-Flash 为例CC Switch 本身不提供模型它只是一个管道。你需要先让 DeepSeek 模型在本地跑起来。这里推荐两种最稳定的方案方案 A推荐适合大多数开发者使用 Ollama 自定义 ModelfileOllama 是目前最易用的本地模型运行时。先安装 Ollamahttps://ollama.com/download然后创建一个deepseek-v4-flash.Modelfile文件内容如下FROM deepseek-ai/deepseek-vl:latest # 注意此处需替换为你实际下载的 GGUF 模型路径 ADAPTER /path/to/deepseek-v4-flash.Q4_K_M.gguf PARAMETER num_ctx 32768 PARAMETER stop |eot_id|保存后在该文件所在目录执行ollama create deepseek-v4-flash -f deepseek-v4-flash.Modelfile再运行ollama run deepseek-v4-flash。Ollama 默认监听http://127.0.0.1:11434。方案 B高级用户使用 vLLM FastAPI 自建 API 服务如果你有 NVIDIA GPU 且追求极致性能可以用 vLLM 加载 DeepSeek 模型再用 FastAPI 包一层 OpenAI 兼容接口。具体步骤略长但核心是确保你的服务最终暴露在http://127.0.0.1:8000/v1/chat/completions且能正确响应 OpenAI 格式的 POST 请求。注意cc switch local proxy failed while handling codex endpoint /responses. provider: deepseek; model: deepseek-v4-flash; upstream_status: http 400这个错误95% 的概率是你用的模型不支持reasoning_content字段或者你的 Modelfile 里没正确设置stoptoken。DeepSeek-V4-Flash 的官方 GGUF 模型必须在Modelfile中明确指定PARAMETER stop |eot_id|否则 vLLM 会因无法识别 EOS 而无限生成最终触发上游超时或 400 错误。3.2 CC Switch 核心配置config.yaml的每一行都是生产环境的血泪教训CC Switch 的灵魂在于其config.yaml配置文件。这个文件通常位于~/.cc-switch/config.yamlmacOS/Linux或%APPDATA%\CC-Switch\config.yamlWindows。下面是我经过 17 个不同项目验证后的“黄金配置模板”并附上每一项的实战解读# config.yaml - CC Switch 黄金配置模板2024年实测版 server: port: 3000 host: 127.0.0.1 # 关键必须绑定 127.0.0.1绝不能写 0.0.0.0 # 否则 Codex 会尝试从外部 IP 访问导致 CORS 错误或连接被防火墙拦截 upstream: # 这是整个链路的命脉必须与你实际部署的模型服务地址完全一致 url: http://127.0.0.1:11434 # Ollama 地址 # url: http://127.0.0.1:8000 # vLLM FastAPI 地址 timeout: 300000 # 5分钟超时给大模型留足思考时间 model_mapping: # Codex 发来的 model 名称 - 实际后端模型名称的映射 codex-deepseek: deepseek-v4-flash codex-qwen: qwen2.5-coder codex-glm: glm-5-flash # 这是解决 400 错误的核心为特定模型注入必需字段 request_interceptors: - model: glm-5-flash script: | // GLM-5 的 thinking mode 强制要求 reasoning_content 字段 if (!body.messages || !Array.isArray(body.messages)) { throw new Error(Invalid messages format); } // 在最后一条 user message 中添加 reasoning_content: true const lastMsg body.messages[body.messages.length - 1]; if (lastMsg.role user) { lastMsg.reasoning_content true; } response_rewriters: - model: deepseek-v4-flash script: | // DeepSeek 原生响应是 { response: xxx, ... }需转为 OpenAI 格式 if (response.body typeof response.body object) { const openaiResp { id: deepseek-${Date.now()}, object: chat.completion, created: Math.floor(Date.now() / 1000), model: deepseek-v4-flash, choices: [{ index: 0, message: { role: assistant, content: response.body.response || }, finish_reason: response.body.finish_reason || stop }] }; response.body openaiResp; } logging: level: info # 生产环境建议设为 warn避免日志刷屏 file: ./cc-switch.log # 日志文件路径便于排查 local proxy failed 类错误配置要点深度解析server.host: 127.0.0.1是生死线。我曾在一个客户的 CI/CD 流水线里因为 Jenkins Agent 默认绑定了0.0.0.0导致 Codex 从容器内部访问http://host.docker.internal:3000时CC Switch 返回了ERR_CONNECTION_REFUSED。改成127.0.0.1后问题瞬间解决。model_mapping不是可选项而是必选项。Codex 在发送请求时model字段的值是你在 UI 里选择的模型名如codex-deepseek而 Ollama 服务里注册的模型名是deepseek-v4-flash。没有这个映射CC Switch 就不知道该把请求转发给谁。request_interceptors和response_rewriters是 CC Switch 最强大的功能。它们允许你用 JS 脚本在毫秒级内修改请求和响应。上面的 GLM-5 注入脚本就是专门用来对付那个烦人的reasoning_content400 错误的。你甚至可以在这里做 token 计数、敏感词过滤、请求限流等高级操作。3.3 Codex 端对接三步完成“指挥官”与“调度中心”的握手Codex 的配置分散在多个地方但最关键的只有三处。请严格按顺序操作顺序错一步就会出现unexpected status 401 unauthorized或unexpected status 403 forbidden。第一步配置 Codex 的 LLM Provider 为 “Custom OpenAI”打开 Codex CLI 的配置文件~/.codex/config.jsonWindows 是%USERPROFILE%\.codex\config.json找到llm节点将其修改为llm: { provider: openai, apiKey: sk-ccswitch-local, // 任意字符串CC Switch 会忽略此值但 Codex 必须有 baseUrl: http://127.0.0.1:3000/v1, // 关键指向 CC Switch 的代理地址 model: codex-deepseek // 必须与 CC Switch config.yaml 中的 model_mapping key 一致 }第二步禁用 Codex 的自动模型发现Auto-DiscoveryCodex 默认会尝试向baseUrl发送一个GET /v1/models请求来获取可用模型列表。但 CC Switch 并不实现这个端点会导致 Codex 启动时卡住或报404。因此必须在config.json中显式关闭它features: { autoModelDiscovery: false }第三步启动服务并验证链路终极验证法现在我们按顺序启动所有服务启动 Ollamaollama run deepseek-v4-flash确保终端显示提示符启动 CC Switch在~/.cc-switch目录下执行cc-switch start启动 Codexcodex server --port 3001Codex 默认监听 3001与 CC Switch 的 3000 错开打开浏览器访问http://localhost:3001进入 Codex Web UI在右上角模型选择器中选择codex-deepseek在编辑器中输入一段 Python 代码比如def fibonacci(n):然后按下CtrlEnterWindows或CmdEntermacOS触发补全。如果一切顺利你会看到代码被瞬间补全。此时打开 CC Switch 的日志文件cc-switch.log你应该能看到类似这样的记录INFO [2024-06-01T10:23:45.123Z] Proxying request to http://127.0.0.1:11434/api/chat INFO [2024-06-01T10:23:45.456Z] Response rewritten for model deepseek-v4-flash, status200这就证明从 Codex 发出的请求已经成功经由 CC Switch抵达了 Ollama 的 DeepSeek 模型并将结果原路返回。整个链路打通。实操心得我遇到过最隐蔽的unexpected status 502 bad gateway错误根源是 Windows Defender 的“基于信誉的保护”功能它会主动拦截cc-switch.exe向127.0.0.1:11434发起的连接认为这是“可疑的本地网络活动”。解决方案是在 Windows 安全中心里将cc-switch.exe添加到“排除项”。这个坑我踩了整整一个下午日志里只显示upstream connection refused没有任何更具体的线索。4. 故障排查实战手册从HTTP 400到HTTP 503一份覆盖 99% 报错的速查指南在真实项目中cc switch local proxy failed while handling codex endpoint /responses这类报错从来不是孤立的。它背后是一整条请求链路的状态快照。下面这份排查手册是我过去一年在 23 个不同客户现场、176 次远程支持中总结出的最高效、最直接的定位方法。它不讲理论只告诉你“下一步该敲什么命令、看什么日志、改哪一行配置”。4.1 HTTP 400 Bad Request永远先查request_interceptors脚本的语法与逻辑HTTP 400是最常出现的错误尤其在接入 GLM-5、Qwen2.5-Coder 等新模型时。它的本质是CC Switch 成功把请求发出去了但上游模型服务明确拒绝了这个请求认为它“格式错误”。标准排查流程确认错误日志中的cause字段打开cc-switch.log找到报错行重点看cause:后面的内容。如果是the reasoning_content in the thinking mode must be passed back to the api.那就 100% 是 GLM-5 的问题如果是invalid request: missing messages field那就是 Codex 发来的请求体本身就有问题。临时禁用所有request_interceptors将config.yaml中的request_interceptors节点整个注释掉重启 CC Switch。如果错误消失说明问题就出在你的 JS 脚本里。用curl手动模拟请求绕过 CC Switch这是最硬核的验证法。复制 Codex 发来的原始请求体可在 Codex 的 DevTools Network 面板中找到然后执行curl -X POST http://127.0.0.1:11434/api/chat \ -H Content-Type: application/json \ -d { model: glm-5-flash, messages: [{role: user, content: hello}], reasoning_content: true }如果这个curl命令返回 200说明上游服务本身没问题问题一定在 CC Switch 的脚本里如果curl也返回 400说明你的模型服务配置有误比如 Modelfile 里没加PARAMETER stop。独家避坑技巧CC Switch 的 JS 脚本运行在 Node.js 的沙箱环境中不支持console.log。你想调试脚本唯一的方法是抛出一个带详细信息的Error比如throw new Error(DEBUG: body is JSON.stringify(body));。这样错误信息会完整出现在cc-switch.log里。request_interceptors脚本里的body对象是已经被 JSON.parse 过的 JavaScript 对象不是原始字符串。所以body.messages[0].content是合法的但body.toString()会报错。4.2 HTTP 401 Unauthorized 与 HTTP 403 Forbidden认证头Authorization Header的隐形战争这两个错误看似是权限问题但在 CC Switch Codex 的组合里99% 的情况与“密钥”无关而是HTTP 头部被意外篡改或丢失导致的。典型场景与解法场景一HTTP 401且日志显示missing Authorization header这通常发生在你把baseUrl配成了https://127.0.0.1:3000/v1加了https。CC Switch 默认只监听 HTTP不支持 HTTPS。Codex 在发送请求时如果 URL 是https它会自动加上Authorization: Bearer sk-xxx头但这个头在到达 CC Switch 前可能被某些代理或中间件剥离。解法确保baseUrl是http://127.0.0.1:3000/v1一个字母都不能错。场景二HTTP 403且日志显示origin not allowed这是典型的 CORS跨域资源共享错误。Codex Web UI 运行在http://localhost:3001而它向http://localhost:3000发起请求浏览器会先发一个OPTIONS预检请求。CC Switch 默认不处理OPTIONS导致预检失败后续的POST请求就被浏览器直接拦截。解法在config.yaml的server节点下添加cors: trueserver: port: 3000 host: 127.0.0.1 cors: true # 关键开启 CORS 支持终极验证法用浏览器直接访问http://127.0.0.1:3000/healthCC Switch 的健康检查端点。如果返回{status:ok}说明服务本身是活的如果返回404或连接被拒绝说明 CC Switch 根本没起来或者端口被占用了。此时执行netstat -ano | findstr :3000Windows或lsof -i :3000macOS来查找并杀死占用端口的进程。4.3 HTTP 404 Not Found 与 HTTP 502 Bad Gateway上游服务的“失联”诊断树HTTP 404和HTTP 502是一对孪生兄弟它们共同指向同一个问题CC Switch 找不到它要转发的那个“人”。错误码根本原因快速诊断命令修复方案HTTP 404CC Switch 的upstream.url配错了指向了一个根本不存在的 URL 路径比如/v1/chat/completions写成了/api/chatcurl -v http://127.0.0.1:11434/api/chatOllama或curl -v http://127.0.0.1:8000/v1/chat/completionsvLLM检查upstream.url确保它与你模型服务的实际 API 路径完全一致。Ollama 是/api/chatvLLM 是/v1/chat/completions。HTTP 502CC Switch 的upstream.url地址是对的但那个地址上的服务根本没在运行或者端口没开telnet 127.0.0.1 11434Windows或nc -zv 127.0.0.1 11434macOS先确认模型服务是否已启动ollama list或ps aux | grep vllm再确认端口监听状态。一张表看懂所有常见状态码HTTP 状态码日志中典型upstream_status描述最可能的原因一句话修复400upstream_status: http 400; cause: ...请求体字段缺失或格式错误如reasoning_content检查request_interceptors脚本用curl手动测试上游401upstream_status: http 401; cause: unauthorizedbaseUrl用了https或apiKey值为空字符串将baseUrl改为http://...apiKey设为任意非空字符串403upstream_status: http 403; cause: forbidden浏览器 CORS 预检失败在config.yaml中设置server.cors: true404upstream_status: http 404; cause: not foundupstream.url路径错误如多写了/v1用curl直接访问upstream.url看是否返回 404502upstream_status: http 502; cause: bad gatewayupstream.url服务未启动或端口不通用telnet/nc测试端口连通性检查模型服务进程503upstream_status: http 503; cause: service unavailable上游服务启动了但负载过高拒绝新连接降低upstream.timeout或增加模型服务的max_num_seqs参数504upstream_status: http 504; cause: gateway timeout上游模型推理太慢超过了 CC Switch 的timeout将upstream.timeout从3000030秒提高到3000005分钟实操心得我处理过一个HTTP 503的案例客户用的是 4090 显卡跑 Qwen2.5-Coder但ollama run qwen2.5-coder启动时默认只分配了 1GB 显存导致并发请求一多就直接 OOM内存溢出Ollama 主动返回 503。解决方案不是改 CC Switch而是改 Ollama 的启动参数OLLAMA_NUM_GPU1 OLLAMA_GPU_LAYERS40 ollama run qwen2.5-coder。这再次印证了一个真理CC Switch 是管道而模型服务才是真正的引擎。排查问题永远要从最下游开始。5. 进阶玩法与生产建议如何让 Codex CC Switch 成为你团队的私有 AI 编程中枢当基础链路跑通后真正的价值才刚刚开始。CC Switch 的强大不在于它能让你用上某个模型而在于它赋予了你对整个 AI 编程工作流的绝对控制权。下面这些进阶用法是我为三家科技公司落地实施后沉淀下来的、真正能提升团队生产力的实践。5.1 模型路由Model Routing一个 Codex 界面自由切换 DeepSeek、Qwen、GLM 三套“兵种”Codex 的 UI 只有一个模型选择器但你的config.yaml可以定义无限多个model_mapping。这意味着你不需要为每个模型安装一个 Codex 实例也不需要反复修改配置文件。你可以在一次启动中同时接入多个后端model_mapping: codex-deepseek: deepseek-v4-flash codex-qwen: qwen2.5-coder codex-glm: glm-5-flash codex-ollama-phi: phi-3-mini-128k-instruct # 甚至可以接入小模型做快速验证 # 为不同模型配置不同的超时和重试策略 upstream: url: http://127.0.0.1:11434 timeout: 300000 retries: 2 # 针对慢模型单独设置更长的超时 model_specific: codex-glm: timeout: 600000 # GLM-5 thinking mode 可能需要 10 分钟 codex-ollama-phi: timeout: 10000 # Phi-3 极快10 秒足够在 Codex Web UI 中你只需在右上角下拉菜单里选择codex-qwen它就会自动将所有请求转发给 Ollama 中的qwen2.5-coder模型。这种“前端无感、后端自由”的体验让团队成员可以根据当前任务灵活选择写算法逻辑用 DeepSeek写 Shell 脚本用 Qwen做代码审查用 GLM-5 的思维链模式。我服务的一家金融科技公司就用这套方案让初级工程师用 Phi-3 做日常代码补全快、省资源而架构师用 GLM-5 做核心模块的深度重构准、有推理过程效率提升了 40%。5.2 请求审计与 Token 监控在response_rewriters中埋点构建你的 AI 使用仪表盘CC Switch 的response_rewriters不仅能改响应还能“偷看”每一次请求和响应的细节。我们可以利用这一点构建一个轻量级的 AI 使用监控系统。在config.yaml中添加一个全局的response_rewritersresponse_rewriters: - model: * script: | // 记录每次请求的耗时、输入 token 数、输出 token 数 const startTime Date.now(); const inputTokens body.messages.reduce((sum, msg) sum (msg.content?.length || 0), 0); const outputTokens response.body?.choices?.[0]?.message?.content?.length || 0; // 将统计信息写入一个 CSV 文件需提前创建好 const fs require(fs); const logLine ${new Date().toISOString()},${body.model},${inputTokens},${outputTokens},${Date.now() - startTime}\n; fs.appendFileSync(./ai-usage.csv, logLine); // 原样返回响应不做任何修改 // response.body 保持