Skip to content

Commit

Permalink
grpc: add h2c listener in the http port.
Browse files Browse the repository at this point in the history
  • Loading branch information
hugosantos committed Oct 18, 2023
1 parent d972bb1 commit 959eb5b
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 5 deletions.
37 changes: 33 additions & 4 deletions std/go/grpc/servercore/listener.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import (
"github.com/rs/zerolog/hlog"
"github.com/soheilhy/cmux"
"go.uber.org/automaxprocs/maxprocs"
"golang.org/x/net/http2"
"golang.org/x/net/http2/h2c"
"google.golang.org/grpc"
"google.golang.org/grpc/health"
"google.golang.org/grpc/health/grpc_health_v1"
Expand All @@ -28,9 +30,23 @@ import (
"namespacelabs.dev/foundation/std/grpc/requestid"
)

type HTTPOptions struct {
HTTP1ReadTimeout time.Duration `json:"http_read_timeout"`
HTTP1ReadHeaderTimeout time.Duration `json:"http_read_header_timeout"`
HTTP1WriteTimeout time.Duration `json:"http_write_timeout"`
HTTP1IdleTimeout time.Duration `json:"http_idle_timeout"`
HTTP1MaxHeaderBytes int `json:"http_max_header_bytes"`

HTTP2MaxConcurrentStreams uint32 `json:"http2_max_concurrent_streams"`
HTTP2MaxReadFrameSize uint32 `json:"http2_max_read_frame_size"`
HTTP2IdleTimeout time.Duration `json:"http2_idle_timeout"`
HTTP2MaxUploadBufferPerConnection int32 `json:"http2_max_upload_buffer_per_connection"`
HTTP2MaxUploadBufferPerStream int32 `json:"http2_max_upload_buffer_per_stream"`
}

type ListenOpts struct {
CreateListener func(context.Context) (net.Listener, error)
CreateHttpListener func(context.Context) (net.Listener, error)
CreateHttpListener func(context.Context) (net.Listener, HTTPOptions, error)

DontHandleSigTerm bool
}
Expand Down Expand Up @@ -129,13 +145,26 @@ func Listen(ctx context.Context, opts ListenOpts, registerServices func(Server))
go func() { checkReturn("grpc", grpcServer.Serve(anyL)) }()

if opts.CreateHttpListener != nil {
httpServer := &http.Server{Handler: httpMux}

gwLis, err := opts.CreateHttpListener(ctx)
gwLis, opts, err := opts.CreateHttpListener(ctx)
if err != nil {
return err
}

httpServer := &http.Server{
Handler: h2c.NewHandler(httpMux, &http2.Server{
MaxConcurrentStreams: opts.HTTP2MaxConcurrentStreams,
MaxReadFrameSize: opts.HTTP2MaxReadFrameSize,
IdleTimeout: opts.HTTP2IdleTimeout,
MaxUploadBufferPerConnection: opts.HTTP2MaxUploadBufferPerConnection,
MaxUploadBufferPerStream: opts.HTTP2MaxUploadBufferPerStream,
}),
ReadTimeout: opts.HTTP1ReadTimeout,
ReadHeaderTimeout: opts.HTTP1ReadHeaderTimeout,
WriteTimeout: opts.HTTP1WriteTimeout,
IdleTimeout: opts.HTTP1IdleTimeout,
MaxHeaderBytes: opts.HTTP1MaxHeaderBytes,
}

core.ZLog.Info().Msgf("Starting HTTP listen on %v", gwLis.Addr())

go func() { checkReturn("http", httpServer.Serve(gwLis)) }()
Expand Down
17 changes: 16 additions & 1 deletion std/go/server/grpcserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,13 @@ package server

import (
"context"
"encoding/json"
"flag"
"net"
"time"

"google.golang.org/grpc/codes"
"namespacelabs.dev/foundation/framework/rpcerrors"
"namespacelabs.dev/foundation/std/go/core"
"namespacelabs.dev/foundation/std/go/grpc/servercore"
)
Expand All @@ -17,6 +21,7 @@ var (
listenHostname = flag.String("listen_hostname", "localhost", "Hostname to listen on.")
port = flag.Int("grpcserver_port", 0, "Port to listen on.")
httpPort = flag.Int("grpcserver_http_port", 0, "Port to listen HTTP on.")
httpOptions = flag.String("grpc_http_options", "{}", "Options to pass to the HTTP server.")
)

const drainTimeout = 30 * time.Second
Expand Down Expand Up @@ -44,8 +49,18 @@ func makeListenerOpts() servercore.ListenOpts {
opts := servercore.ListenOpts{
CreateListener: servercore.MakeTCPListener(*listenHostname, *port),
}

if *httpPort != 0 {
opts.CreateHttpListener = servercore.MakeTCPListener(*listenHostname, *httpPort)
opts.CreateHttpListener = func(ctx context.Context) (net.Listener, servercore.HTTPOptions, error) {
var parsed servercore.HTTPOptions
if err := json.Unmarshal([]byte(*httpOptions), &parsed); err != nil {
return nil, servercore.HTTPOptions{}, rpcerrors.Errorf(codes.Internal, "failed to parse http options: %w", err)
}

lst, err := servercore.MakeTCPListener(*listenHostname, *httpPort)(ctx)
return lst, parsed, err
}
}

return opts
}

0 comments on commit 959eb5b

Please sign in to comment.