Bartek
Bartek

Reputation: 15599

How do I adjust Go's http Client (or Transport) to mimic curls --http2-prior-knowledge flag?

I'm interacting with a server (that is out of my control) in which protocol upgrade is not performed by the server if a request contains content (POST, PUT, PATCH with payload). It's unclear exactly what the issue with the server is, but I noticed that when I query with --http2-prior-knowledge, the protocol is upgraded:

❯ curl -i -PUT --http2-prior-knowledge  http://localhost:8081/document/v1/foo -d '{"fields": {"docid": "123"}}'
HTTP/2 200 
date: Tue, 08 Nov 2022 13:26:50 GMT
content-type: application/json;charset=utf-8
vary: Accept-Encoding
content-length: 78

The same request without --http2-prior-knowledge is stuck at HTTP/1.1. This seems closer to the default behaviour of Go's HTTP client

❯ curl -i -PUT --http2 http://localhost:8081/document/v1/foo -d '{"fields": {"docid": "123"}}'
HTTP/1.1 200 OK
Date: Tue, 08 Nov 2022 01:37:17 GMT
Content-Type: application/json;charset=utf-8
Vary: Accept-Encoding
Content-Length: 78

When I call this same API using Go's default client, the protocol is not upgraded. I've tried setting ForceAttemptHTTP2: true on the transport, but each http.Response contains a .Proto of HTTP/1.1

I think what I need to understand is how I can mimic curl's prior-knowledge flag in Go. Is this possible?

Upvotes: 2

Views: 846

Answers (1)

Bartek
Bartek

Reputation: 15599

I solved this issue by specifying a custom http2.Transport which skipped TLS dial. The ideal solution, in retrospect, is to use an SSL certificate (self-signed is sufficient) which would better guarantee the use of HTTP2. Leaving some links for posterity

c := &http.Client{
        // Skip TLS Dial
        Transport: &http2.Transport{
           AllowHTTP: true,
           DialTLS: func(netw, addr string, cfg *tls.Config) (net.Conn, error) {
              return net.Dial(netw, addr)
           },
        },
}

And links:

Upvotes: 1

Related Questions