func main() { var srv http.Server flag.BoolVar(&http2.VerboseLogs, "verbose", false, "Verbose HTTP/2 debugging.") flag.Parse() srv.Addr = *httpsAddr registerHandlers() if *prod { *hostHTTP = "http2.golang.org" *hostHTTPS = "http2.golang.org" log.Fatal(serveProd()) } url := "https://" + httpsHost() + "/" log.Printf("Listening on " + url) http2.ConfigureServer(&srv, &http2.Server{}) if *httpAddr != "" { go func() { log.Printf("Listening on http://" + httpHost() + "/ (for unencrypted HTTP/1)") log.Fatal(http.ListenAndServe(*httpAddr, nil)) }() } go func() { log.Fatal(srv.ListenAndServeTLS("server.crt", "server.key")) }() select {} }
func serveProdTLS() error { c, err := googlestorage.NewServiceClient() if err != nil { return err } slurp := func(key string) ([]byte, error) { const bucket = "http2-demo-server-tls" rc, _, err := c.GetObject(&googlestorage.Object{ Bucket: bucket, Key: key, }) if err != nil { return nil, fmt.Errorf("Error fetching GCS object %q in bucket %q: %v", key, bucket, err) } defer rc.Close() return ioutil.ReadAll(rc) } certPem, err := slurp("http2.golang.org.chained.pem") if err != nil { return err } keyPem, err := slurp("http2.golang.org.key") if err != nil { return err } cert, err := tls.X509KeyPair(certPem, keyPem) if err != nil { return err } srv := &http.Server{ TLSConfig: &tls.Config{ Certificates: []tls.Certificate{cert}, }, } http2.ConfigureServer(srv, &http2.Server{}) ln, err := net.Listen("tcp", ":443") if err != nil { return err } return srv.Serve(tls.NewListener(tcpKeepAliveListener{ln.(*net.TCPListener)}, srv.TLSConfig)) }
// serveUsingHandler is called from handleRawConn when s is configured // to handle requests via the http.Handler interface. It sets up a // net/http.Server to handle the just-accepted conn. The http.Server // is configured to route all incoming requests (all HTTP/2 streams) // to ServeHTTP, which creates a new ServerTransport for each stream. // serveUsingHandler blocks until conn closes. // // This codepath is only used when Server.TestingUseHandlerImpl has // been configured. This lets the end2end tests exercise the ServeHTTP // method as one of the environment types. // // conn is the *tls.Conn that's already been authenticated. func (s *Server) serveUsingHandler(listenerAddr net.Addr, conn net.Conn) { if !s.addConn(conn) { conn.Close() return } defer s.removeConn(conn) connDone := make(chan struct{}) hs := &http.Server{ Handler: s, ConnState: func(c net.Conn, cs http.ConnState) { if cs == http.StateClosed { close(connDone) } }, } if err := http2.ConfigureServer(hs, &http2.Server{ MaxConcurrentStreams: s.opts.maxConcurrentStreams, }); err != nil { grpclog.Fatalf("grpc: http2.ConfigureServer: %v", err) return } hs.Serve(&singleConnListener{addr: listenerAddr, conn: conn}) <-connDone }