drpc icon indicating copy to clipboard operation
drpc copied to clipboard

http based drpc client

Open vtolstov opened this issue 3 years ago • 8 comments

i'm try to create api gateway that support http rest, grpc and drpc on the same port

i'm create grpc server, drpc http handler, and plain http handler and use the in http2 server as handler.

plain http and grpc works fine, but drpc request does not goes to http2 server =( does it possible to get this worked with native drpc clients ?

gsrv := grpc.NewServer(grpc.UnknownServiceHandler(h.ServeGRPC))
comboHandler := newComboMux(h, gsrv, drpchttp.New(h))
http2Server := &http2.Server{}
hs := &http.Server{Handler: h2c.NewHandler(comboHandler, http2Server)}
func (h *Handler) ServeDRPC(stream drpc.Stream, rpc string) error {
	ctx := stream.Context()
	logger.Infof(ctx, "drpc: %#+v", rpc)
	return nil
}

func (h *Handler) HandleRPC(stream drpc.Stream, rpc string) error {
	return h.ServeDRPC(stream, rpc)
}

func newComboMux(httph http.Handler, grpch http.Handler, drpch http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.ProtoMajor == 2 {
			ct := r.Header.Get("content-type")
			switch {
			case strings.HasPrefix(ct, "application/grpc"):
				grpch.ServeHTTP(w, r)
				return
			case strings.HasPrefix(ct, "application/drpc"):
				drpch.ServeHTTP(w, r)
				return
			}
		}
		httph.ServeHTTP(w, r)
	})
}

vtolstov avatar Mar 20 '22 20:03 vtolstov

as i understand that drpc does not send any http2 headers by default so its not possible to determine how to handle this request in this combo server ? does it possible to handle native drpc client without drpcmigrate client helper that sends special bytes before data?

vtolstov avatar Mar 20 '22 20:03 vtolstov

What do you mean by "native drpc client?" Since it's going through http, something has to exist to map the http request into a drpc stream, which is a drpchttp.Protocol with the built in ones defined here. There's no built in way for a drpc client to wrap a request into an http request, though.

zeebo avatar Mar 21 '22 19:03 zeebo

Let me explain - with grpc i can handle incoming grpc connections to http2 server. Parse incoming stream data and get service/method and payload. With drpc - i cant handle simple drpc connection created with tcp connect and drpc.New()

vtolstov avatar Mar 21 '22 20:03 vtolstov

how can i create drpc connection to http based drpc server that can switch protocol by content-type header ?

vtolstov avatar Mar 21 '22 20:03 vtolstov

may be i need to create drpc.Transport that utilise http1/http2 connection?

vtolstov avatar Mar 21 '22 20:03 vtolstov

can you add to drpchttp transport that uses http connection for drpc?

vtolstov avatar Mar 21 '22 20:03 vtolstov

One option might be to use a websocket based transport like https://pkg.go.dev/go.bryk.io/pkg/net/drpc/ws

zeebo avatar Mar 23 '22 17:03 zeebo

This will be a tracking issue to extend the drpchttp package to include a client that wraps an http.Transport or something. It may be limited to unitary streams. It'd be cool if it worked against twirp or grpc-web servers as well as the basic drpchttp server.

zeebo avatar Sep 22 '22 14:09 zeebo