如何在Go http服务器中解析http Get请求的请求体?

huangapple go评论80阅读模式
英文:

How to parse http Get request body in a Go http server?

问题

在Go的http服务器中,我可以获取POST请求的请求体。Go的net/http包似乎删除了GET请求的请求体。我知道最好不要使用带有请求体的http GET,但我需要处理带有请求体的http GET。是否可以在不更改标准库的情况下实现?请帮忙,因为我不想切换回使用libevent的C语言!

当客户端发送带有请求体的POST请求时,下面的代码将显示请求体内容。但是当客户端发送带有请求体的GET请求时,请求体中没有任何内容。

func handler(w http.ResponseWriter, r *http.Request) {
    defer r.Body.Close()
    body, _ := ioutil.ReadAll(r.Body)
    
    log.Printf("body: %v", string(body))
}

func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":8080", nil)
}
英文:

In a Go http server, I can get POST request body. Go net/http package seems to remove GET request body. I know it is better not to use http GET with request body,but I need to handle http GET with request body. Is it possible without changing the standard lib?
Please help since I don't want to switch back to C with libevent!

When a client sends a POST with request body, below code will show the body content. But when a client sends a GET with request body, there is nothing in the body.

func handler(w http.ResponseWriter, r *http.Request) {
	defer r.Body.Close()
	body, _ := ioutil.ReadAll(r.Body)
	
	log.Printf("body: %v", string(body))
}

func main() {
	http.HandleFunc("/", handler)
	http.ListenAndServe(":8080", nil)
}

答案1

得分: 3

大部分的魔法发生在transfer.go中。在fixLength函数中,我找到了以下看起来相关的内容:

如果不是响应且请求方法是“GET”,则会执行以下操作:
// RFC 2616并没有明确允许或禁止在GET请求中使用实体主体,因此如果声明了实体主体,我们允许使用一个,但是如果没有提到主体,则默认为0(而不是下面的-1)。
return 0, nil

看起来,只要客户端在结束时发送了Content-Length头部,就没问题。如果没有发送,该库将假设在GET请求中没有主体。

由于您的客户端正在执行一些非常不寻常/错误的操作,您有点超出了地图的边缘。如果您可以修复客户端,那是最好的选择。

也就是说,如果您需要支持一个错误的客户端,您将不得不自己解决一些问题。您不需要完全转向C和libevent。只需将标准库中的net/http包复制到您的项目中并进行修改。然后将导入语句更改为指向您版本的库。

或者,如果您知道客户端不使用keep-alive,您可以“劫持”连接并只读取套接字上剩余的内容。

英文:

Most of the magic happens in transfer.go. Here's what I found that looks relevant in the fixLength func:

if !isResponse && requestMethod == "GET" {
	// RFC 2616 doesn't explicitly permit nor forbid an
	// entity-body on a GET request so we permit one if
	// declared, but we default to 0 here (not -1 below)
	// if there's no mention of a body.
	return 0, nil
}

Looks like, as long as your client is ending a Content-Length header, you're all good. If not, the library will assume there's no body on a GET request.

You're kind of off the edge of the map as your client is doing some pretty unusual/broken stuff. If you can fix the client, that's your best bet.

That said, if you have a client you need to support that's doing this wrong, you're going to have to roll some things yourself. You don't need to go all the way down to C and libevent. Simply copy the net/http package from the standard library into your project and modify it. Then change your import statements to point at your version of the library.

Alternatively, if you know that the client is not using keep-alive, you can Hijack the connection and just read whatever's left on the socket.

huangapple
  • 本文由 发表于 2013年7月16日 20:19:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/17676334.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定