Example #1
0
// AddSPDY adds SPDY support to srv, and must be called before srv begins serving.
func AddSPDY(srv *http.Server) {
	npnStrings := npn()
	if len(npnStrings) <= 1 {
		return
	}
	if srv.TLSConfig == nil {
		srv.TLSConfig = new(tls.Config)
	}
	if srv.TLSConfig.NextProtos == nil {
		srv.TLSConfig.NextProtos = npnStrings
	} else {
		// Collect compatible alternative protocols.
		others := make([]string, 0, len(srv.TLSConfig.NextProtos))
		for _, other := range srv.TLSConfig.NextProtos {
			if !strings.Contains(other, "spdy/") && !strings.Contains(other, "http/") {
				others = append(others, other)
			}
		}

		// Start with spdy.
		srv.TLSConfig.NextProtos = make([]string, 0, len(others)+len(npnStrings))
		srv.TLSConfig.NextProtos = append(srv.TLSConfig.NextProtos, npnStrings[:len(npnStrings)-1]...)

		// Add the others.
		srv.TLSConfig.NextProtos = append(srv.TLSConfig.NextProtos, others...)
		srv.TLSConfig.NextProtos = append(srv.TLSConfig.NextProtos, "http/1.1")
	}
	if srv.TLSNextProto == nil {
		srv.TLSNextProto = make(map[string]func(*http.Server, *tls.Conn, http.Handler))
	}
	for _, str := range npnStrings {
		switch str {
		case "spdy/2":
			srv.TLSNextProto[str] = func(s *http.Server, tlsConn *tls.Conn, handler http.Handler) {
				conn, err := NewServerConn(tlsConn, s, 2)
				if err != nil {
					log.Println(err)
					return
				}
				conn.Run()
				conn = nil
				runtime.GC()
			}
		case "spdy/3":
			srv.TLSNextProto[str] = func(s *http.Server, tlsConn *tls.Conn, handler http.Handler) {
				conn, err := NewServerConn(tlsConn, s, 3)
				if err != nil {
					log.Println(err)
					return
				}
				conn.Run()
				conn = nil
				runtime.GC()
			}
		}
	}
}
Example #2
0
File: spdy.go Project: vonwenm/spdy
// AddSPDY adds SPDY support to srv, and must be called before srv begins serving.
func AddSPDY(srv *http.Server) {
	if srv == nil {
		return
	}

	npnStrings := npn()
	if len(npnStrings) <= 1 {
		return
	}
	if srv.TLSConfig == nil {
		srv.TLSConfig = new(tls.Config)
	}
	if srv.TLSConfig.NextProtos == nil {
		srv.TLSConfig.NextProtos = npnStrings
	} else {
		// Collect compatible alternative protocols.
		others := make([]string, 0, len(srv.TLSConfig.NextProtos))
		for _, other := range srv.TLSConfig.NextProtos {
			if !strings.Contains(other, "spdy/") && !strings.Contains(other, "http/") {
				others = append(others, other)
			}
		}

		// Start with spdy.
		srv.TLSConfig.NextProtos = make([]string, 0, len(others)+len(npnStrings))
		srv.TLSConfig.NextProtos = append(srv.TLSConfig.NextProtos, npnStrings[:len(npnStrings)-1]...)

		// Add the others.
		srv.TLSConfig.NextProtos = append(srv.TLSConfig.NextProtos, others...)
		srv.TLSConfig.NextProtos = append(srv.TLSConfig.NextProtos, "http/1.1")
	}
	if srv.TLSNextProto == nil {
		srv.TLSNextProto = make(map[string]func(*http.Server, *tls.Conn, http.Handler))
	}
	for _, str := range npnStrings {
		switch str {
		case "spdy/2":
			srv.TLSNextProto[str] = spdy2.NextProto
		case "spdy/3":
			srv.TLSNextProto[str] = spdy3.NextProto
		case "spdy/3.1":
			srv.TLSNextProto[str] = spdy3.NextProto1
		}
	}
}
Example #3
0
// ConfigureServer adds HTTP/2 support to http.Server.
func ConfigureServer(hs *http.Server, conf *Server) {
	// Mostof the code in this function was copied from
	// https://github.com/bradfitz/http2/blob/master/server.go
	if conf == nil {
		conf = new(Server)
	}
	if hs.TLSConfig == nil {
		hs.TLSConfig = new(tls.Config)
	}

	hs.TLSConfig.NextProtos = append(hs.TLSConfig.NextProtos, H2Protos...)

	if hs.TLSNextProto == nil {
		hs.TLSNextProto = map[string]func(*http.Server, *tls.Conn, http.Handler){}
	}
	for _, proto := range H2Protos {
		hs.TLSNextProto[proto] = func(hs *http.Server, c *tls.Conn, h http.Handler) {
			conf.handleConn(hs, c, h)
		}
	}
}
Example #4
0
// UpgradeServer operates similarly to ConfigureServer() with the exception that
// it returns a clone copy of the original server that will be used to
// exclusively serve HTTP/1.1 and HTTP/1.0 requests. The "HTTP/2 Configured"
// server passed to UpgradeServer() should not be modified once this call has
// been made, nor should it actively be listening for new connections.
//
// When an existing HTTP/1.1 connection requests an upgrade to h2c or h2c-14 mode,
// the connection will be hijacked from the "clone server" (as returned by
// UpgradeServer() and handed off to the internal http2 configured server.
//
// Ex usage:
//
// http.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) {
// 				rw.Header().Set("Content-Type", "text/plain")
// 				fmt.Fprintf(rw, "response to %v\n", r)
// })
//
// s := http2.UpgradeServer(&http.Server{Addr:":8080"},nil)
// s.ListenAndServe()
//
// NB: Do *not* alter the returned server's Handler, as it is hooked in order to
// perform the protocol switch. Any changes to uri handling must be made in the
// "inner" server *before* it is passed to UpgradeServer(). The standard
// http.DefaultServeMux will always be used as a last resort.
//
// NB: Note that HTTP/1.1 requests with bodies (i.e. HTTP POST) are not
// supported in the initial Upgrade request but will work once the connection
// is fully HTTP/2. Requests that have content entities will automatically
// fallback to HTTP/1.1 (the upgrade silently fails but the normal handler
// is invoked).
func UpgradeServer(s *http.Server, conf *Server) *http.Server {
	if conf == nil {
		conf = new(Server)
	}

	handler := s.Handler
	if handler == nil {
		handler = http.DefaultServeMux
	}

	h1s := new(http.Server)
	*h1s = *s
	h1s.TLSConfig = nil
	h1s.TLSNextProto = nil
	h1s.Handler = &upgradeMux{
		handler: handler,
		srv:     s,
		conf:    conf,
	}

	ConfigureServer(s, conf)
	return h1s
}