UPDATE (2015/10/15): HTTP/2 is now enabled by default for http servers in tip and will be released as part of Go 1.6. That means that you will be able to create HTTP/2 servers without even calling
ConfigureServer()
.At #golang tip @HTTP_2 server now enabled by default. https://t.co/dcaTfboGVe & https://t.co/c8xbVtBqRe Thx @enneff, @bmizerany & others!
— Brad Fitzpatrick (@bradfitz) October 14, 2015
HTTP/2 is a new version of HTTP with added functionality, including connection multiplexing and header compression. There is currently no HTTP/2 implementation in the Go standard library, but there are a couple of libraries under development that you can use to create HTTP/2 servers and clients in Go.
The canonical library is the golang.org/x/net/http2 library by Brad Fitzpatrick. This library will eventually be added to the Go standard library, but it currently lives in a separate package while under development. It’s still under active development so your milage may vary, but you should probably use this library if you are implementing an HTTP/2 server.
Create an HTTP/2 Server
Using the http2 library to write a server is fairly easy. The http2 library
integrates with the http package in the standard library. You just need to make
a call to http2.ConfigureServer()
to configure a normal http server to use
HTTP/2. You will need to set up TLS encryption if accessing your server via a
browser or it will fall back to using HTTP 1.x. Though encryption isn’t
required, no browser clients currently support unencrypted HTTP/2.
package main
import (
"log"
"net/http"
"os"
"golang.org/x/net/http2"
)
func main() {
cwd, err := os.Getwd()
if err != nil {
log.Fatal(err)
}
srv := &http.Server{
Addr: ":8000", // Normally ":443"
Handler: http.FileServer(http.Dir(cwd)),
}
http2.ConfigureServer(srv, &http2.Server{})
log.Fatal(srv.ListenAndServeTLS("server.crt", "server.key"))
}
Create an HTTP/2 Client
Currently the implementation in the http2
library is pretty hacky. Although
it spits out lots of debug style logging, it works for the most part. You use
an http2.Transport
object and pass it to a normal client from the http
package.
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
"golang.org/x/net/http2"
)
func main() {
client := http.Client{
// InsecureTLSDial is temporary and will likely be
// replaced by a different API later.
Transport: &http2.Transport{InsecureTLSDial: true},
}
resp, err := client.Get("https://localhost:8000/")
if err != nil {
log.Fatal(err)
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(body))
}
Further Reading
If you’re interested in learning more about HTTP/2 you can check out the HTTP/2 homepage, which has lots of links to other material and implementations in other languages.
If you are interested in a deeper look at how HTTP/2 clients and servers are
implemented one alternative implementation worth exploring is Jxck’s http2
implementation. Jxck implements HTTP/2 handling
by hooking into TLSNextProto
on a standard HTTP
server. You can see a sample use of
it here.
The grpc-go library also has its own implementation of an HTTP/2 client and server in the transport package.