Skip to content

Commit

Permalink
Add gRPC Gateway interceptors option (#51)
Browse files Browse the repository at this point in the history
  • Loading branch information
Nir Shirion authored Dec 27, 2021
1 parent 2f30334 commit 9d0b364
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 11 deletions.
16 changes: 14 additions & 2 deletions constructors/partial/httpserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,16 @@ const (
FxGroupExternalHTTPHandlers = "externalHttpHandlers"
// FxGroupExternalHTTPHandlerFunctions defines group name
FxGroupExternalHTTPHandlerFunctions = "externalHttpHandlerFunctions"
// FxGroupExternalHTTPInterceptors defines group name
FxGroupExternalHTTPInterceptors = "externalHttpInterceptors"
// FxGroupUnaryServerInterceptors defines group name
FxGroupUnaryServerInterceptors = "unaryServerInterceptors"
// FxGroupInternalHTTPHandlers defines group name
FxGroupInternalHTTPHandlers = "internalHttpHandlers"
// FxGroupInternalHTTPHandlerFunctions defines group name
FxGroupInternalHTTPHandlerFunctions = "internalHttpHandlerFunctions"
// FxGroupInternalHTTPInterceptors defines group name
FxGroupInternalHTTPInterceptors = "internalHttpInterceptors"
)

// HTTPHandlerPatternPair defines pattern -> handler pair
Expand Down Expand Up @@ -65,9 +69,11 @@ type httpServerDeps struct {
GRPCGatewayMuxOptions []runtime.ServeMuxOption `group:"grpcGatewayMuxOptions"`
ExternalHTTPHandlers []HTTPHandlerPatternPair `group:"externalHttpHandlers"`
ExternalHTTPHandlerFunctions []HTTPHandlerFuncPatternPair `group:"externalHttpHandlerFunctions"`
ExternalHTTPInterceptors []serverInt.GRPCGatewayInterceptor `group:"externalHttpInterceptors"`
// Internal REST
InternalHTTPHandlers []HTTPHandlerPatternPair `group:"internalHttpHandlers"`
InternalHTTPHandlerFunctions []HTTPHandlerFuncPatternPair `group:"internalHttpHandlerFunctions"`
InternalHTTPHandlers []HTTPHandlerPatternPair `group:"internalHttpHandlers"`
InternalHTTPHandlerFunctions []HTTPHandlerFuncPatternPair `group:"internalHttpHandlerFunctions"`
InternalHTTPInterceptors []serverInt.GRPCGatewayInterceptor `group:"internalHttpInterceptors"`
}

// HTTPServerBuilder true to it's name, it is partially initialized builder.
Expand Down Expand Up @@ -108,6 +114,9 @@ func (deps httpServerDeps) buildExternalAPI(builder serverInt.GRPCWebServiceBuil
for _, handlerFuncPair := range deps.ExternalHTTPHandlerFunctions {
restBuilder = restBuilder.AddHandlerFunc(handlerFuncPair.Pattern, handlerFuncPair.HandlerFunc)
}
if len(deps.ExternalHTTPInterceptors) > 0 {
restBuilder = restBuilder.AddGRPCGatewayInterceptors(deps.ExternalHTTPInterceptors...)
}
if len(deps.GRPCGatewayGeneratedHandlers) > 0 {
restBuilder = restBuilder.AddGRPCGatewayOptions(deps.GRPCGatewayMuxOptions...).
RegisterGRPCGatewayHandlers(deps.GRPCGatewayGeneratedHandlers...)
Expand All @@ -134,6 +143,9 @@ func (deps httpServerDeps) buildInternalAPI(builder serverInt.GRPCWebServiceBuil
for _, handlerFuncPair := range deps.InternalHTTPHandlerFunctions {
restBuilder = restBuilder.AddHandlerFunc(handlerFuncPair.Pattern, handlerFuncPair.HandlerFunc)
}
if len(deps.InternalHTTPInterceptors) > 0 {
restBuilder = restBuilder.AddGRPCGatewayInterceptors(deps.InternalHTTPInterceptors...)
}
restBuilder = restBuilder.RegisterGRPCGatewayHandlers(health.RegisterInternalGRPCGatewayHandler) // Health
builder = restBuilder.BuildRESTPart()
}
Expand Down
24 changes: 16 additions & 8 deletions http/server/builders.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,15 @@ import (
// ******************************************************************************************************************************************************

type restConfig struct {
addr string
server *http.Server
listener net.Listener
handlers map[string]http.Handler
handlerFuncs map[string]http.HandlerFunc
grpcGatewayMux *runtime.ServeMux
grpcGatewayHandlers []server.GRPCGatewayGeneratedHandlers
grpcGatewayOptions []runtime.ServeMuxOption
addr string
server *http.Server
listener net.Listener
handlers map[string]http.Handler
handlerFuncs map[string]http.HandlerFunc
grpcGatewayMux *runtime.ServeMux
grpcGatewayHandlers []server.GRPCGatewayGeneratedHandlers
grpcGatewayOptions []runtime.ServeMuxOption
grpcGatewayInterceptors []server.GRPCGatewayInterceptor
}

type restBuilder struct {
Expand Down Expand Up @@ -102,6 +103,13 @@ func (r *restBuilder) AddGRPCGatewayOptions(options ...runtime.ServeMuxOption) s
return r
}

func (r *restBuilder) AddGRPCGatewayInterceptors(interceptors ...server.GRPCGatewayInterceptor) server.RESTBuilder {
r.ll.PushBack(func(cfg *restConfig) {
cfg.grpcGatewayInterceptors = append(cfg.grpcGatewayInterceptors, interceptors...)
})
return r
}

func (r *restBuilder) BuildRESTPart() server.GRPCWebServiceBuilder {
for e := r.ll.Front(); e != nil; e = e.Next() {
f := e.Value.(func(cfg *restConfig))
Expand Down
6 changes: 5 additions & 1 deletion http/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,11 @@ func (ws *webService) setupREST(restConfigs []*restConfig) (err error) {
emptyListener = false
}
if muxHandler, ok := webSrv.Handler.(muxHandler); ok {
muxHandler.Handle("/", gwMux)
var gwHandler http.Handler = gwMux
for _, interceptor := range cfg.grpcGatewayInterceptors {
gwHandler = interceptor(gwHandler)
}
muxHandler.Handle("/", gwHandler)
} else {
return fmt.Errorf("grpc Gateway handlers can't be registered, since the provided *http.Server can't handle them")
}
Expand Down
32 changes: 32 additions & 0 deletions http/server/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,38 @@ func TestCustomGrpcGatewayMux(t *testing.T) {
assert.Equal(t, "bad one", strings.TrimSpace(string(bytes)))
}

func TestCustomGrpcGatewayInterceptor(t *testing.T) {
service, err := Builder().
ListenOn("localhost:8888").
RegisterGRPCAPIs(registerGrpcAPI).
AddRESTServerConfiguration().
ListenOn("localhost:8889").
RegisterGRPCGatewayHandlers(registerGatewayHandler).
AddGRPCGatewayInterceptors(func(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/" {
w.WriteHeader(http.StatusTeapot)
w.Write([]byte("bad one"))
return
}

handler.ServeHTTP(w, r)
})
}).
BuildRESTPart().
Build()
require.NoError(t, err)
defer service.Stop(context.Background()) // clean
go service.Run(context.Background())
resp, err := http.Get("http://localhost:8889/")
require.NoError(t, err)
defer resp.Body.Close()
assert.Equal(t, http.StatusTeapot, resp.StatusCode)
bytes, err := ioutil.ReadAll(resp.Body)
require.NoError(t, err)
assert.Equal(t, "bad one", strings.TrimSpace(string(bytes)))
}

func registerGrpcAPI(srv *grpc.Server) {
demopackage.RegisterDemoServer(srv, new(demopackage.UnimplementedDemoServer))
}
Expand Down
4 changes: 4 additions & 0 deletions interfaces/http/server/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ type GRPCWebServiceBuilder interface {
// GRPCGatewayGeneratedHandlers alias for gRPC-gateway endpoint registrations
type GRPCGatewayGeneratedHandlers func(mux *runtime.ServeMux, endpoint string) error

// GRPCGatewayInterceptor alias for gRPC-gateway interceptor
type GRPCGatewayInterceptor func(handler http.Handler) http.Handler

// RESTBuilder defines REST web service builder options
type RESTBuilder interface {
ListenOn(addr string) RESTBuilder
Expand All @@ -64,5 +67,6 @@ type RESTBuilder interface {
SetCustomGRPCGatewayMux(mux *runtime.ServeMux) RESTBuilder
RegisterGRPCGatewayHandlers(handlers ...GRPCGatewayGeneratedHandlers) RESTBuilder
AddGRPCGatewayOptions(options ...runtime.ServeMuxOption) RESTBuilder
AddGRPCGatewayInterceptors(interceptors ...GRPCGatewayInterceptor) RESTBuilder
BuildRESTPart() GRPCWebServiceBuilder
}
18 changes: 18 additions & 0 deletions interfaces/http/server/mock/mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions providers/groups/alias.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ const (
// ExternalHTTPHandlerFunctions - External Http Handlers function group, add your custom external HTTP Handler Functions
ExternalHTTPHandlerFunctions = partial.FxGroupExternalHTTPHandlerFunctions

// ExternalHTTPInterceptors - External Http Interceptors group, add your custom external HTTP interceptors
ExternalHTTPInterceptors = partial.FxGroupExternalHTTPInterceptors

// UnaryServerInterceptors - GRPC Unary Server Interceptors group. Register different gRPC server interceptors
UnaryServerInterceptors = partial.FxGroupUnaryServerInterceptors

Expand All @@ -37,6 +40,9 @@ const (
//InternalHTTPHandlerFunctions - Internal Http Handler Functions group. Similar toInternalHttpHandlers but for functions
InternalHTTPHandlerFunctions = partial.FxGroupInternalHTTPHandlerFunctions

// InternalHTTPInterceptors - Internal Http Interceptors group, add your custom external HTTP interceptors
InternalHTTPInterceptors = partial.FxGroupInternalHTTPInterceptors

// LoggerContextExtractors - Default Logger Context extractors group. Add custom extractors to enrich your logs from context.Context
LoggerContextExtractors = constructors.FxGroupLoggerContextExtractors

Expand Down

0 comments on commit 9d0b364

Please sign in to comment.