Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

http.Request RequestURI field when making request in go

Tags:

http

go

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?

like image 230
Sławosz Avatar asked Oct 25 '13 17:10

Sławosz


1 Answers

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.

like image 171
ANisus Avatar answered Oct 19 '22 04:10

ANisus