Compare commits
5 Commits
89f016ed9d
...
v0.9.2
Author | SHA1 | Date | |
---|---|---|---|
4f0c5fe665 | |||
5c26accc34 | |||
f8279d9653 | |||
b44b6a331c | |||
adfedc9239 |
5
TODO.md
5
TODO.md
@ -1,11 +1,12 @@
|
|||||||
# TODO
|
# TODO
|
||||||
|
|
||||||
- [ ] Test and troubleshoot GRPC Gateway supprot
|
|
||||||
- [ ] Finish implementing GRPC service support
|
|
||||||
- [ ] Expand config test case to cover GRPC config
|
- [ ] Expand config test case to cover GRPC config
|
||||||
- [ ] Expand tracing
|
- [ ] Expand tracing
|
||||||
|
|
||||||
## Done
|
## Done
|
||||||
|
|
||||||
|
- [x] Test and troubleshoot GRPC Gateway supprot
|
||||||
|
- [x] Finish implementing GRPC service support
|
||||||
- [x] Unit tests
|
- [x] Unit tests
|
||||||
- [x] Pattern for extending config
|
- [x] Pattern for extending config
|
||||||
- [x] HTTP Logging Middleware
|
- [x] HTTP Logging Middleware
|
||||||
|
@ -44,13 +44,11 @@ func (a *App) MustRun() {
|
|||||||
// Prepare GRPC first. The GRPC server may update its opts
|
// Prepare GRPC first. The GRPC server may update its opts
|
||||||
// with a prepared GRPC-Gateway runtime.ServeMux if any of its services
|
// with a prepared GRPC-Gateway runtime.ServeMux if any of its services
|
||||||
// have added GRPC-Gateway handlers. If present, serve under api path
|
// have added GRPC-Gateway handlers. If present, serve under api path
|
||||||
if a.cfg.GRPCEnabled() {
|
a.runGRPC(ctx)
|
||||||
a.runGRPC(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
if a.cfg.HTTPEnabled() {
|
// Second, prepare and run HTTP server, embedding grpc-gateway
|
||||||
a.runHTTP(ctx)
|
// runtime.ServeMux if set by runGRPC()
|
||||||
}
|
a.runHTTP(ctx)
|
||||||
|
|
||||||
// Monitor app lifecycle
|
// Monitor app lifecycle
|
||||||
go a.monitor()
|
go a.monitor()
|
||||||
|
@ -3,14 +3,26 @@ package app
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"github.com/rs/zerolog"
|
||||||
"go.opentelemetry.io/otel/attribute"
|
"go.opentelemetry.io/otel/attribute"
|
||||||
"go.opentelemetry.io/otel/codes"
|
"go.opentelemetry.io/otel/codes"
|
||||||
"go.opentelemetry.io/otel/trace"
|
"go.opentelemetry.io/otel/trace"
|
||||||
|
|
||||||
"gitea.libretechconsulting.com/rmcguire/go-app/pkg/srv/http/opts"
|
optsgrpc "gitea.libretechconsulting.com/rmcguire/go-app/pkg/srv/grpc/opts"
|
||||||
|
optshttp "gitea.libretechconsulting.com/rmcguire/go-app/pkg/srv/http/opts"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (a *App) runGRPC(ctx context.Context) {
|
func (a *App) runGRPC(ctx context.Context) {
|
||||||
|
if a.GRPC == nil {
|
||||||
|
a.GRPC = &optsgrpc.AppGRPC{
|
||||||
|
GRPCDone: make(chan error),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !a.cfg.GRPCEnabled() {
|
||||||
|
zerolog.Ctx(ctx).Info().Msg("skipping disabled GRPC server")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
span := trace.SpanFromContext(ctx)
|
span := trace.SpanFromContext(ctx)
|
||||||
if err := a.initGRPC(ctx); err != nil {
|
if err := a.initGRPC(ctx); err != nil {
|
||||||
span.RecordError(err)
|
span.RecordError(err)
|
||||||
@ -21,10 +33,10 @@ func (a *App) runGRPC(ctx context.Context) {
|
|||||||
|
|
||||||
if a.GRPC.GetGatewayMux() != nil {
|
if a.GRPC.GetGatewayMux() != nil {
|
||||||
if a.HTTP.Handlers == nil {
|
if a.HTTP.Handlers == nil {
|
||||||
a.HTTP.Handlers = make([]opts.HTTPHandler, 0, 1)
|
a.HTTP.Handlers = make([]optshttp.HTTPHandler, 0, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
a.HTTP.Handlers = append(a.HTTP.Handlers, opts.HTTPHandler{
|
a.HTTP.Handlers = append(a.HTTP.Handlers, optshttp.HTTPHandler{
|
||||||
Prefix: a.cfg.GRPC.GRPCGatewayPath,
|
Prefix: a.cfg.GRPC.GRPCGatewayPath,
|
||||||
StripPrefix: true,
|
StripPrefix: true,
|
||||||
Handler: a.GRPC.GetGatewayMux(),
|
Handler: a.GRPC.GetGatewayMux(),
|
||||||
|
@ -3,12 +3,26 @@ package app
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"github.com/rs/zerolog"
|
||||||
"go.opentelemetry.io/otel/attribute"
|
"go.opentelemetry.io/otel/attribute"
|
||||||
"go.opentelemetry.io/otel/codes"
|
"go.opentelemetry.io/otel/codes"
|
||||||
"go.opentelemetry.io/otel/trace"
|
"go.opentelemetry.io/otel/trace"
|
||||||
|
|
||||||
|
optshttp "gitea.libretechconsulting.com/rmcguire/go-app/pkg/srv/http/opts"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (a *App) runHTTP(ctx context.Context) {
|
func (a *App) runHTTP(ctx context.Context) {
|
||||||
|
if a.HTTP == nil {
|
||||||
|
a.HTTP = &optshttp.AppHTTP{
|
||||||
|
HTTPDone: make(chan any),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !a.cfg.HTTPEnabled() {
|
||||||
|
zerolog.Ctx(ctx).Info().Msg("skipping disabled HTTP Server")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
span := trace.SpanFromContext(ctx)
|
span := trace.SpanFromContext(ctx)
|
||||||
if err := a.initHTTP(ctx); err != nil {
|
if err := a.initHTTP(ctx); err != nil {
|
||||||
span.RecordError(err)
|
span.RecordError(err)
|
||||||
|
@ -2,6 +2,7 @@ package grpc
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
@ -18,7 +19,7 @@ func (a *appGRPCServer) registerServiceGatewayHandlers(ctx context.Context, serv
|
|||||||
if len(service.GwRegistrationFuncs) < 1 {
|
if len(service.GwRegistrationFuncs) < 1 {
|
||||||
return
|
return
|
||||||
} else if a.gatewayMux == nil {
|
} else if a.gatewayMux == nil {
|
||||||
a.gatewayMux = runtime.NewServeMux()
|
a.gatewayMux = runtime.NewServeMux(a.opts.GRPCGatewayOpts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, span := a.tracer.Start(ctx, "appgrpc.init.prepare.service.gwHandlers", trace.WithAttributes(
|
ctx, span := a.tracer.Start(ctx, "appgrpc.init.prepare.service.gwHandlers", trace.WithAttributes(
|
||||||
@ -29,8 +30,15 @@ func (a *appGRPCServer) registerServiceGatewayHandlers(ctx context.Context, serv
|
|||||||
|
|
||||||
clientConn := a.GetClientConn(ctx)
|
clientConn := a.GetClientConn(ctx)
|
||||||
|
|
||||||
|
var errs error
|
||||||
for _, registerGW := range service.GwRegistrationFuncs {
|
for _, registerGW := range service.GwRegistrationFuncs {
|
||||||
registerGW(ctx, a.gatewayMux, clientConn)
|
errs = errors.Join(errs, registerGW(ctx, a.gatewayMux, clientConn))
|
||||||
|
a.logger.Debug().Any("fwo", a.gatewayMux.GetForwardResponseOptions()).
|
||||||
|
Msg("calling gateway registration func")
|
||||||
|
}
|
||||||
|
|
||||||
|
if errs != nil {
|
||||||
|
panic(errs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,6 +58,7 @@ func (a *appGRPCServer) GetClientConn(ctx context.Context) *grpc.ClientConn {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
span.RecordError(err)
|
span.RecordError(err)
|
||||||
span.SetStatus(codes.Error, err.Error())
|
span.SetStatus(codes.Error, err.Error())
|
||||||
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return clientConn
|
return clientConn
|
||||||
|
@ -10,8 +10,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type GRPCOpts struct {
|
type GRPCOpts struct {
|
||||||
*config.GRPCConfig
|
*config.GRPCConfig // Settings configurable by env or yaml
|
||||||
*AppGRPC
|
*AppGRPC // Settings provided in code
|
||||||
}
|
}
|
||||||
|
|
||||||
type AppGRPC struct {
|
type AppGRPC struct {
|
||||||
@ -19,7 +19,8 @@ type AppGRPC struct {
|
|||||||
UnaryInterceptors []grpc.UnaryServerInterceptor
|
UnaryInterceptors []grpc.UnaryServerInterceptor
|
||||||
StreamInterceptors []grpc.StreamServerInterceptor
|
StreamInterceptors []grpc.StreamServerInterceptor
|
||||||
GRPCOpts []grpc.ServerOption
|
GRPCOpts []grpc.ServerOption
|
||||||
GRPCDialOpts []grpc.DialOption // Map ServerOptions to DialOpts for GRPC Gateway support
|
GRPCDialOpts []grpc.DialOption // Map ServerOptions to DialOpts for GRPC Gateway support
|
||||||
|
GRPCGatewayOpts []runtime.ServeMuxOption // Configure grpc-gateway ServeMux
|
||||||
GRPCDone <-chan error
|
GRPCDone <-chan error
|
||||||
gatewayMux *runtime.ServeMux
|
gatewayMux *runtime.ServeMux
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||||
@ -60,8 +61,15 @@ func prepHTTPServer(opts *opts.AppHTTP) *http.Server {
|
|||||||
// Inject extra handlers if given
|
// Inject extra handlers if given
|
||||||
// Used for grpc-gateway runtime.ServeMux handlers
|
// Used for grpc-gateway runtime.ServeMux handlers
|
||||||
for _, h := range opts.Handlers {
|
for _, h := range opts.Handlers {
|
||||||
|
// prefix must end in / to route sub-paths
|
||||||
|
if !strings.HasSuffix(h.Prefix, "/") {
|
||||||
|
h.Prefix = h.Prefix + "/"
|
||||||
|
}
|
||||||
|
|
||||||
|
// if enabled, the path prefix is stripped before
|
||||||
|
// requests are sent to the handler
|
||||||
if h.StripPrefix {
|
if h.StripPrefix {
|
||||||
h.Handler = http.StripPrefix(h.Prefix, h.Handler)
|
h.Handler = http.StripPrefix(h.Prefix[:len(h.Prefix)-1], h.Handler)
|
||||||
}
|
}
|
||||||
mux.Handle(h.Prefix, h.Handler)
|
mux.Handle(h.Prefix, h.Handler)
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user