Golang中HTTP响应状态码200但返回空body的问题如何解决
Golang中HTTP响应状态码200但返回空body的问题如何解决 我正在尝试编写一个库来与 Jetbrains Space HTTP API 进行交互,但遇到了一些问题。当我向他们的 API 提交 HTTP 请求时,即使实际情况并非如此,我总是收到 200 OK 状态码。
以下是我发送给服务器的请求:
POST /api/http/projects HTTP/1.1
Host: dragonfly.jetbrains.space
User-Agent: Go-http-client/1.1
Content-Length: 78
Authorization: Bearer <oauth2 access token>
Accept-Encoding: gzip
Accept: application/json
{"description":"","key":{"key":"ABC"},"name":"Test","private":true,"tags":[]}
使用的代码如下:
buf := bytes.NewBuffer(nil)
_ = json.NewEncoder(buf).Encode(map[string]interface{}{
"key": map[string]interface{}{"key": "ABC"},
"name": "Test",
"private": true,
"description": "",
"tags": []string{},
})
req, err := http.NewRequest("POST", "https://dragonfly.jetbrains.space/api/http/projects", buf)
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer <oauth2 access token>")
req.Header.Set("Accept", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
我期望看到的是 403 Forbidden 状态码,并附带以下错误信息:
{"error":"permission-denied","error_description":"Only users are allowed to perform this operation"}
但我最终得到的是:
HTTP/2.0 200 OK
Content-Length: 0
Date: Sat, 23 May 2020 10:13:21 GMT
Vary: Origin
对于这些错误,使用 Go HTTP 客户端时,我似乎总是收到 200 OK 状态码且没有响应体数据。我尝试用 JavaScript 发送相同的请求,结果似乎正常,这让我相信这是 Go HTTP 客户端的某个特殊问题。
同样的问题也出现在不同的端点上,但奇怪的是,如果对端点的调用成功,它却能正常工作。(即一个真正的 200 OK)
有人能给我一些指点吗?
感谢您提供的任何帮助。
更多关于Golang中HTTP响应状态码200但返回空body的问题如何解决的实战教程也可以访问 https://www.itying.com/category-94-b0.html
事实证明,缺少一个请求头导致端点返回了状态码为200 OK但无响应体的结果。显然,我之前使用的JavaScript库会自动包含这个请求头。
更多关于Golang中HTTP响应状态码200但返回空body的问题如何解决的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
这是一个典型的HTTP/2协议处理问题。Jetbrains Space API在某些错误情况下会发送HTTP/2的RST_STREAM帧,而Go的HTTP客户端在遇到这种情况时会返回200状态码和空响应体。
以下是解决方案:
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
)
func main() {
buf := bytes.NewBuffer(nil)
_ = json.NewEncoder(buf).Encode(map[string]interface{}{
"key": map[string]interface{}{"key": "ABC"},
"name": "Test",
"private": true,
"description": "",
"tags": []string{},
})
req, err := http.NewRequest("POST", "https://dragonfly.jetbrains.space/api/http/projects", buf)
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer <oauth2 access token>")
req.Header.Set("Accept", "application/json")
// 方案1:强制使用HTTP/1.1
transport := &http.Transport{
ForceAttemptHTTP2: false, // 禁用HTTP/2
}
client := &http.Client{
Transport: transport,
}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Printf("Status: %d\n", resp.StatusCode)
// 读取响应体
var result map[string]interface{}
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
fmt.Printf("Error reading response: %v\n", err)
} else {
fmt.Printf("Response: %v\n", result)
}
}
或者使用更精细的HTTP/2配置:
// 方案2:配置HTTP/2的ReadIdleTimeout
transport := &http.Transport{
ReadIdleTimeout: 30 * time.Second, // 防止HTTP/2连接过早关闭
}
client := &http.Client{
Transport: transport,
Timeout: 30 * time.Second,
}
resp, err := client.Do(req)
如果问题仍然存在,可以添加详细的错误处理来诊断:
resp, err := client.Do(req)
if err != nil {
// 检查是否是HTTP/2 RST_STREAM错误
if strings.Contains(err.Error(), "stream reset") ||
strings.Contains(err.Error(), "RST_STREAM") {
fmt.Println("HTTP/2 stream was reset by server")
}
panic(err)
}
// 检查响应体是否为空
body, err := io.ReadAll(resp.Body)
if err != nil {
fmt.Printf("Error reading body: %v\n", err)
}
if len(body) == 0 && resp.StatusCode == 200 {
fmt.Println("Received empty body with 200 status - likely HTTP/2 issue")
}
这个问题在Go 1.16及更高版本中更为常见,因为默认启用了HTTP/2。强制使用HTTP/1.1是最可靠的解决方案。

