7

How can I force a simple Go client to use HTTP/2 and prevent it from falling back to HTTP 1.1 ?

I have a simple HTTP/2 server running on "localhost" and it returns details of the request in its reply. Here is the output using Google Chrome for this URL: https://localhost:40443/bananas

I like bananas!
Method       = GET
URL          = /bananas
Proto        = HTTP/2.0
Host         = localhost:40443
RequestURI   = /bananas

But here is what I get for my Go client code. You can see it falls back to HTTP 1.1

I like monkeys!
Method       = GET
URL          = /monkeys
Proto        = HTTP/1.1
Host         = localhost:40443
RequestURI   = /monkeys

Below is the source code of my best attempt to contact the same server using HTTP/2, but it always falls back to HTTP 1.1

// simple http/2 client

package main

import (
    "crypto/tls"
    "crypto/x509"
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
)

const (
    certFile = "client-cert.pem"
    keyFile  = "client-key.pem"
    caFile   = "server-cert.pem"
)

func main() {
    // Load client certificate
    cert, err := tls.LoadX509KeyPair(certFile, keyFile)
    if err != nil {
        log.Fatal(err)
    }

    // Load CA cert
    caCert, err := ioutil.ReadFile(caFile)
    if err != nil {
        log.Fatal(err)
    }
    caCertPool := x509.NewCertPool()
    caCertPool.AppendCertsFromPEM(caCert)

    // Setup HTTPS client
    tlsConfig := &tls.Config{
        Certificates: []tls.Certificate{cert},
        RootCAs:      caCertPool,
    }
    tlsConfig.BuildNameToCertificate()
    transport := &http.Transport{TLSClientConfig: tlsConfig}
    client := &http.Client{Transport: transport}

    response, err := client.Get("https://localhost:40443/monkeys")
    if err != nil {
        log.Fatal(err)
    }
    defer response.Body.Close()

    // dump response
    text, err := ioutil.ReadAll(response.Body)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("Body:\n%s", text)
}

Any suggestions would be appreciated, including pointers to other working examples that illustrate how to make HTTP/2 client requests in Go.

1

1 Answer 1

12

First import "golang.org/x/net/http2" package. And then change

transport := &http.Transport{TLSClientConfig: tlsConfig}

to

transport := &http2.Transport{TLSClientConfig: tlsConfig}
Sign up to request clarification or add additional context in comments.

2 Comments

It would be nice if HTTP/2 was be supported transparently, as some of the documentation suggests, but it seems that once you start adding configuration options, you lost that transparency and need to refer to http2 explicitly.
How do we achieve the same (forcing the client to use http2) in a webserver with Java?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.