简单的HTTPS请求:Golang返回505,Python和Chrome运行正常

I'm attempting to perform an HTTP get over TLS using the simplest imaginable golang code and getting a 505 response from a server (HTTP version not supported). The thing is, with a simple python requests.get the same query works. Also, I can use Chrome and perform the same request successfully.

Any ideas what makes the golang request different that would cause the server to return the 505?

I realize that this response is server specific. HTTPS to google.com with the same golang code works. I've attempted troubleshooting with Wireshark but TLS makes this difficult. It seems like this must be something simple! The server is nginx 1.9.3.

Golang code:

package main

import (
        "fmt"
        "net/http"
        "time"
)

func main() {
        url := "https://non-public-address/page"
        tr := &http.Transport{
                MaxIdleConns:       10,
                IdleConnTimeout:    30 * time.Second,
                DisableCompression: false,
        }
        client := &http.Client{Transport: tr}
        resp, _ := client.Get(url)
        fmt.Println(resp)
}

Python:

r = requests.get("https://non-public-address/page")
print(r)

I figured out the issue eventually by decrypting the traffic in Wireshark. The URL in my Go implementation has spaces and using http.Get didn't URL encode the spaces to %20. With spaces in the GET request the server was misinterpreting the request.

Lesson learned: Go's http.Get does not URL encode characters and you have to do this on your own.

505 is HTTP version not supported.

You did not set an HTTP version on your Transport, and

The DefaultTransport supports HTTP/2.

-- Go net/http package docs

Support of the HTTP/2 protocol was introduced in Nginx 1.9.5.

Since you didn't specify HTTP/2, I would have thought communication would fall back to 1.1 if 2 wasn't supported at the server, but the status in the response and the HTTP versions supported on either side are suspicious.

Transport can be configured to use HTTP/1.1.

Alternatively, don't use a custom Transport:

resp, err := http.Get("https://non-public-address/page")

From the net/http docs/source:

A Client is an HTTP client. Its zero value (DefaultClient) is a usable client that uses DefaultTransport.... DefaultClient is the default Client and is used by Get, Head, and Post.