github.com/Heebron/moby@v0.0.0-20221111184709-6eab4f55faf7/api/server/router/grpc/grpc_routes.go (about)

     1  package grpc // import "github.com/docker/docker/api/server/router/grpc"
     2  
     3  import (
     4  	"context"
     5  	"net/http"
     6  
     7  	"github.com/pkg/errors"
     8  	"golang.org/x/net/http2"
     9  )
    10  
    11  func (gr *grpcRouter) serveGRPC(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
    12  	h, ok := w.(http.Hijacker)
    13  	if !ok {
    14  		return errors.New("handler does not support hijack")
    15  	}
    16  	proto := r.Header.Get("Upgrade")
    17  	if proto == "" {
    18  		return errors.New("no upgrade proto in request")
    19  	}
    20  	if proto != "h2c" {
    21  		return errors.Errorf("protocol %s not supported", proto)
    22  	}
    23  
    24  	conn, _, err := h.Hijack()
    25  	if err != nil {
    26  		return err
    27  	}
    28  	resp := &http.Response{
    29  		StatusCode: http.StatusSwitchingProtocols,
    30  		ProtoMajor: 1,
    31  		ProtoMinor: 1,
    32  		Header:     http.Header{},
    33  	}
    34  	resp.Header.Set("Connection", "Upgrade")
    35  	resp.Header.Set("Upgrade", proto)
    36  
    37  	// set raw mode
    38  	conn.Write([]byte{})
    39  	resp.Write(conn)
    40  
    41  	// https://godoc.org/golang.org/x/net/http2#Server.ServeConn
    42  	// TODO: is it a problem that conn has already been written to?
    43  	gr.h2Server.ServeConn(conn, &http2.ServeConnOpts{Handler: gr.grpcServer})
    44  	return nil
    45  }