You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Golang本地代理遇Transfer-encoding chunked响应乱码问题求助

问题分析与解决方案

你的代理出现乱码的核心原因有两个:一是请求转发时的Header和Body处理不当,二是未适配服务端的chunked编码响应逻辑,另外代码还有几处语法和逻辑问题需要修正。

代码中的问题点

  • 未正确声明变量:newUrl未使用短变量声明(:=),会导致编译错误
  • Header引用传递风险:直接赋值freq.Header = req.Header是引用传递,可能意外修改原请求的Header,应该复制独立的Header副本
  • 请求体丢失:http.NewRequest第三个参数传nil,当原请求带Body时(如POST请求)会丢失请求内容,应直接传递req.Body
  • 响应体转发方式错误:手动读取Body后转成字符串返回,会破坏原响应的chunked编码逻辑,若响应包含压缩内容还会直接导致乱码

修正后的代码

func httpHandler(w http.ResponseWriter, req *http.Request) {
    reqURL := fmt.Sprint(req.URL)
    newUrl := "http://localhost:9098" + reqURL // 修正变量声明

    // 创建转发请求,直接传递原请求体
    freq, reqErr := http.NewRequest(req.Method, newUrl, req.Body)
    if reqErr != nil {
        log.Println(reqErr)
        fmt.Fprintf(w, "Error creating request")
        return
    }
    // 复制原请求Header,避免引用传递
    for k, v := range req.Header {
        freq.Header[k] = append([]string{}, v...)
    }

    client := http.Client{}
    resp, resperr := client.Do(freq)
    if resperr != nil {
        log.Println(resperr)
        fmt.Fprintf(w, "Error. No response")
        return
    }
    defer resp.Body.Close()

    // 复制服务端响应的所有Header到客户端
    for k, v := range resp.Header {
        w.Header()[k] = append([]string{}, v...)
    }
    w.WriteHeader(resp.StatusCode)

    // 直接转发响应体,自动处理chunked编码
    _, err := io.Copy(w, resp.Body)
    if err != nil {
        log.Println("Failed to copy response body:", err)
    }
}

关键修正说明

  1. 变量声明修正:用newUrl :=替代直接赋值,解决未声明变量的编译错误
  2. Header复制:遍历原请求Header并复制值,避免引用传递导致的意外修改
  3. 请求体传递:http.NewRequest直接传入req.Body,确保带Body的请求能正确转发
  4. 响应转发优化:使用io.Copy(w, resp.Body)直接将服务端响应体转发给客户端,Go会自动处理chunked编码、内容编码适配等逻辑,彻底解决乱码问题
  5. 完整Header复制:将服务端返回的所有Header复制到客户端响应中,保证响应头的完整性

内容的提问来源于stack exchange,提问作者mroizo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 20:05:13