Golang处理畸形HTTP版本字符串问题:来自svc_a的POST请求示例"POST /proxy HTTP/1.1"
Golang处理畸形HTTP版本字符串问题:来自svc_a的POST请求示例"POST /proxy HTTP/1.1" (1) 我有一个HTTP客户端,它向HTTP服务器发送以下请求: http.NewRequest(“POST”, “http://localhost:9090/proxy”, strings.NewReader(“This is a POST request from svc_a”))
(2) HTTP服务器通过Go通道将请求对象发送给一个函数(TCP客户端),TCP客户端将HTTP请求作为其有效载荷发送给TCP服务器。
(3) TCP服务器读取TCP有效载荷,并使用http.ReadRequest(x *bufio.Reader)从中创建HTTP请求。 (4) 将响应发送给TCP客户端。
(5) 当我通过同一个套接字连接从TCP客户端向TCP服务器发送两个请求时,有时TCP客户端能成功收到响应,但有时TCP服务器会抛出错误,例如格式错误的HTTP版本“{原始HTTP请求的某部分}”或格式错误的HTTP请求“{” 在http.ReadRequest()这一行。
这里可能是什么原因?是否是由TCP分段引起的?
更多关于Golang处理畸形HTTP版本字符串问题:来自svc_a的POST请求示例"POST /proxy HTTP/1.1"的实战教程也可以访问 https://www.itying.com/category-94-b0.html
看起来HTTP服务器误解了两个连续HTTP请求的边界。你介意捕获并发布pcap文件吗?有几个在线工具可以共享和查看pcap文件(例如cloudshark.org上的CS Enterprise,WireShark的在线版本)
更多关于Golang处理畸形HTTP版本字符串问题:来自svc_a的POST请求示例"POST /proxy HTTP/1.1"的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在Go中处理HTTP请求时,如果遇到畸形HTTP版本字符串错误,通常是由于TCP流中的数据边界问题导致的。当通过同一个TCP连接发送多个请求时,如果读取缓冲区的数据没有正确分割,http.ReadRequest可能会读取到不完整的请求数据或跨请求的数据,从而解析失败。
以下是一个示例,展示如何通过正确管理TCP连接中的数据读取来避免这个问题:
package main
import (
"bufio"
"bytes"
"fmt"
"io"
"net/http"
"strings"
)
// 模拟TCP服务器读取HTTP请求
func readHTTPRequestsFromTCP(conn io.Reader) {
reader := bufio.NewReader(conn)
for {
// 使用http.ReadRequest读取请求
req, err := http.ReadRequest(reader)
if err != nil {
if err == io.EOF {
break
}
fmt.Printf("读取请求失败: %v\n", err)
break
}
defer req.Body.Close()
// 处理请求
body, _ := io.ReadAll(req.Body)
fmt.Printf("收到请求: %s %s 版本: %s 主体: %s\n", req.Method, req.URL.Path, req.Proto, string(body))
}
}
// 模拟TCP客户端发送HTTP请求
func sendHTTPRequestOverTCP(writer io.Writer, req *http.Request) error {
// 将HTTP请求写入缓冲区
var buf bytes.Buffer
if err := req.Write(&buf); err != nil {
return err
}
// 通过TCP连接发送
_, err := writer.Write(buf.Bytes())
return err
}
func main() {
// 创建内存中的管道模拟TCP连接
serverConn, clientConn := io.Pipe()
// 启动模拟TCP服务器
go func() {
readHTTPRequestsFromTCP(serverConn)
serverConn.Close()
}()
// 模拟第一个请求
req1, _ := http.NewRequest("POST", "http://localhost:9090/proxy", strings.NewReader("第一个请求"))
if err := sendHTTPRequestOverTCP(clientConn, req1); err != nil {
fmt.Printf("发送请求1失败: %v\n", err)
}
// 模拟第二个请求
req2, _ := http.NewRequest("POST", "http://localhost:9090/proxy", strings.NewReader("第二个请求"))
if err := sendHTTPRequestOverTCP(clientConn, req2); err != nil {
fmt.Printf("发送请求2失败: %v\n", err)
}
clientConn.Close()
}
在这个示例中,每个HTTP请求通过req.Write完整地序列化后写入TCP连接,确保请求之间没有数据粘连。在TCP服务器端,bufio.Reader会按需读取数据,直到http.ReadRequest解析出一个完整的HTTP请求。
如果问题仍然出现,检查TCP客户端是否在发送请求后正确刷新了数据,以及TCP服务器是否在读取请求时正确处理了数据边界。使用bufio.Reader并确保每个请求完整发送可以避免因TCP分段导致的解析错误。

