How to force client to use http/2? (instead of falling back to http 1.1)
Asked Answered
M

1

6

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.

Meristic answered 19/11, 2018 at 3:11 Comment(1)
possible similar issue github.com/golang/go/issues/14391Sparse
G
11

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

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

to

transport := &http2.Transport{TLSClientConfig: tlsConfig}
Gopher answered 19/11, 2018 at 6:47 Comment(2)
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.Meristic
How do we achieve the same (forcing the client to use http2) in a webserver with Java?Bedivere

© 2022 - 2024 — McMap. All rights reserved.