http.Request RequestURI field when making request in go

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

http.Request RequestURI field when making request in go

问题

你在服务器上将请求转储为[]byte,然后使用ReadRequest方法创建了一个请求,并使用Client.Do方法发送请求。你遇到了一个错误:

http: Request.RequestURI无法在客户端请求中设置。

你能解释一下为什么会出现这个错误吗?

英文:

I dumped request from server to []byte and used ReadRequest to make a request with Client.Do method. I got an error:

> http: Request.RequestURI can't be set in client requests.

Can you explain me why exactly I got this error?

答案1

得分: 17

错误很明显:在进行客户端请求时,不允许设置RequestURI。

http.Request.RequestURI的文档中,它说(我强调):

>RequestURI是客户端发送给服务器的Request-Line(RFC 2616,第5.1节)的未修改的Request-URI。通常应该使用URL字段。在HTTP客户端请求中设置此字段是错误的。

设置RequestURI的原因是在解析请求流时ReadRequest会这样做。

因此,如果要发送请求,您需要设置URL并清除RequestURI。在尝试后,我注意到从ReadRequest返回的请求中的URL对象不会设置所有信息,例如scheme和host。因此,您需要自己设置它,或者只需使用net/url包中的Parse解析一个新的URL:

以下是一些可工作的代码示例:

package main

import (
	"fmt"
	"strings"
	"bufio"
	"net/http"
	"net/url"
)

var rawRequest = `GET /pkg/net/http/ HTTP/1.1
Host: golang.org
Connection: close
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X; de-de) AppleWebKit/523.10.3 (KHTML, like Gecko) Version/3.0.4 Safari/523.10
Accept-Encoding: gzip
Accept-Charset: ISO-8859-1,UTF-8;q=0.7,*;q=0.7
Cache-Control: no-cache
Accept-Language: de,en;q=0.7,en-us;q=0.3

`

func main() {
	b := bufio.NewReader(strings.NewReader(rawRequest))
	
	req, err := http.ReadRequest(b)
	if err != nil {
		panic(err)
	}
	
	// 我们不能设置这个字段。而且它只包含"/pkg/net/http/"。
	req.RequestURI = ""
	
	// 由于req.URL不会设置所有信息,例如协议方案和主机,我们创建一个新的URL。
	u, err := url.Parse("http://golang.org/pkg/net/http/")
	if err != nil {
		panic(err)
	}	
	req.URL = u
	
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	
	fmt.Printf("%#v\n", resp)
}

Playground

注意:play.golang.org会发生错误,因为我们没有执行HTTP请求的权限。

英文:

The error is clear: You are not allowed to have RequestURI set when doing a client request.

In the documentation for http.Request.RequestURI, it says (my emphasis):

>RequestURI is the unmodified Request-URI of the
>Request-Line (RFC 2616, Section 5.1) as sent by the client
>to a server. Usually the URL field should be used instead.
>It is an error to set this field in an HTTP client request.

The reason why it is set is because that is what ReadRequest does when parsing the request stream.

So, you need to set the URL and clear the RequestURI if you want to send it. After making an attempt, I noticed that the URL object in the request returned from ReadRequest will not have all the information set, such as scheme and host. Due to this, you will need to set it yourself, or just parse a new URL using Parse in the net/url package:

Here is some working code for you:

package main

import (
	"fmt"
	"strings"
	"bufio"
	"net/http"
	"net/url"
)

var rawRequest = `GET /pkg/net/http/ HTTP/1.1
Host: golang.org
Connection: close
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X; de-de) AppleWebKit/523.10.3 (KHTML, like Gecko) Version/3.0.4 Safari/523.10
Accept-Encoding: gzip
Accept-Charset: ISO-8859-1,UTF-8;q=0.7,*;q=0.7
Cache-Control: no-cache
Accept-Language: de,en;q=0.7,en-us;q=0.3

`

func main() {
	b := bufio.NewReader(strings.NewReader(rawRequest))
	
	req, err := http.ReadRequest(b)
	if err != nil {
		panic(err)
	}
	
	// We can't have this set. And it only contains "/pkg/net/http/" anyway
	req.RequestURI = ""
	
	// Since the req.URL will not have all the information set,
	// such as protocol scheme and host, we create a new URL
	u, err := url.Parse("http://golang.org/pkg/net/http/")
	if err != nil {
		panic(err)
	}	
	req.URL = u
	
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	
	fmt.Printf("%#v\n", resp)
}

Playground

Ps. play.golang.org will panic, since we don't have the permission to do http requests.

huangapple
  • 本文由 发表于 2013年10月26日 01:18:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/19595860.html
匿名

发表评论

匿名网友

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

确定