Documentation
¶
Overview ¶
Package common provides shared utilities for content services.
Mounting Patterns ¶
This package supports multiple patterns for mounting services at custom paths:
## Pattern A: In-Process (Direct)
Service instance runs in the same process as the HTTP server. Use RegisterXYZServiceHandlerServer or the service's RESTHandler method.
service := backends.NewGORMLikesService(db)
handler := service.RESTHandler(ctx, common.WithEntityParam("songId"))
router.Handle("/songs/{songId}/likes/", handler)
## Pattern B: Remote Endpoint (gRPC Gateway Client)
HTTP gateway connects to a remote gRPC server. Entity ID flows through gRPC metadata.
Gateway side (HTTP server):
mux := common.NewGatewayMux(common.WithEntityParamToMetadata("songId"))
likesv1.RegisterLikesServiceHandlerFromEndpoint(ctx, mux, grpcAddr, opts)
router.Handle("/songs/{songId}/likes/", mux)
gRPC server side:
grpcServer := grpc.NewServer(
grpc.UnaryInterceptor(common.EntityIDFromMetadataInterceptor()),
)
likesv1.RegisterLikesServiceServer(grpcServer, likesService)
Index ¶
- Constants
- func CombinedMetadataInterceptor(userIDContextKey any) grpc.UnaryServerInterceptor
- func EntityIDFromMetadataInterceptor() grpc.UnaryServerInterceptor
- func EntityMetadataOption(opts ...GatewayMuxOption) runtime.ServeMuxOption
- func EntityParamMiddleware(paramName string) func(http.Handler) http.Handler
- func ExtractPathParam(r *http.Request, name string) string
- func GetEntityIDFromContextOrMetadata(ctx context.Context) string
- func GetMountedEntityID(ctx context.Context) string
- func NewGatewayMux(opts ...GatewayMuxOption) *runtime.ServeMux
- func NewGatewayMuxWithOptions(gatewayOpts []GatewayMuxOption, runtimeOpts ...runtime.ServeMuxOption) *runtime.ServeMux
- func UserIDFromMetadataInterceptor(contextKey any) grpc.UnaryServerInterceptor
- func WithMountedEntityID(ctx context.Context, entityID string) context.Context
- func WrapWithEntityExtraction(paramName string, handler http.Handler) http.Handler
- type GatewayMuxOption
- type HandlerConfig
- type HandlerOption
- type MountedEntityContextKey
Constants ¶
const ( // MetadataKeyEntityID is the gRPC metadata key for entity ID. MetadataKeyEntityID = "x-entity-id" // MetadataKeyUserID is the gRPC metadata key for user ID. MetadataKeyUserID = "x-user-id" // DefaultUserIDContextKey is the default context key for the authenticated user ID. // All goapplib services use this same key by default, so a single interceptor can // set the user ID and all services will read it. // Apps can override this per-service using WithUserIDContextKey if needed. DefaultUserIDContextKey = "goapplib:user_id" )
Metadata keys for passing entity context through gRPC.
Variables ¶
This section is empty.
Functions ¶
func CombinedMetadataInterceptor ¶
func CombinedMetadataInterceptor(userIDContextKey any) grpc.UnaryServerInterceptor
CombinedMetadataInterceptor returns a gRPC unary interceptor that reads both entity ID and user ID from incoming metadata.
func EntityIDFromMetadataInterceptor ¶
func EntityIDFromMetadataInterceptor() grpc.UnaryServerInterceptor
EntityIDFromMetadataInterceptor returns a gRPC unary interceptor that reads entity ID from incoming metadata and stores it in context.
Use this on the gRPC server side when the gateway sends entity ID via metadata.
Example:
grpcServer := grpc.NewServer(
grpc.UnaryInterceptor(common.EntityIDFromMetadataInterceptor()),
)
func EntityMetadataOption ¶
func EntityMetadataOption(opts ...GatewayMuxOption) runtime.ServeMuxOption
EntityMetadataOption returns a runtime.ServeMuxOption that extracts path parameters and adds them to gRPC metadata. Use this when you want to configure your own mux.
Example:
mux := runtime.NewServeMux(
common.EntityMetadataOption(common.WithEntityParamToMetadata("songId")),
runtime.WithErrorHandler(myErrorHandler),
runtime.WithMarshalerOption(...),
)
likesv1.RegisterLikesServiceHandlerFromEndpoint(ctx, mux, grpcAddr, opts)
func EntityParamMiddleware ¶
EntityParamMiddleware returns middleware that extracts a path parameter and stores it as the mounted entity ID in context.
func ExtractPathParam ¶
ExtractPathParam extracts a path parameter from the request using multiple strategies. Tries in order: Go 1.22+ PathValue, chi URLParam, gorilla mux Vars.
func GetEntityIDFromContextOrMetadata ¶
GetEntityIDFromContextOrMetadata retrieves entity ID from context first, then falls back to gRPC incoming metadata. Useful for services that support both in-process and remote patterns.
func GetMountedEntityID ¶
GetMountedEntityID retrieves the entity ID from context. Returns empty string if not set.
func NewGatewayMux ¶
func NewGatewayMux(opts ...GatewayMuxOption) *runtime.ServeMux
NewGatewayMux creates a gRPC-gateway ServeMux configured for entity extraction. Use this with RegisterXYZServiceHandlerFromEndpoint for remote gRPC servers.
Example:
mux := common.NewGatewayMux(
common.WithEntityParamToMetadata("songId"),
common.WithExtraMetadata(func(ctx context.Context, r *http.Request) metadata.MD {
return metadata.Pairs("x-custom", r.Header.Get("X-Custom"))
}),
)
likesv1.RegisterLikesServiceHandlerFromEndpoint(ctx, mux, grpcAddr, opts)
func NewGatewayMuxWithOptions ¶
func NewGatewayMuxWithOptions(gatewayOpts []GatewayMuxOption, runtimeOpts ...runtime.ServeMuxOption) *runtime.ServeMux
NewGatewayMuxWithOptions creates a gRPC-gateway ServeMux with entity extraction and additional runtime.ServeMuxOption options.
func UserIDFromMetadataInterceptor ¶
func UserIDFromMetadataInterceptor(contextKey any) grpc.UnaryServerInterceptor
UserIDFromMetadataInterceptor returns a gRPC unary interceptor that reads user ID from incoming metadata and stores it in context with the given key.
Example:
grpcServer := grpc.NewServer(
grpc.ChainUnaryInterceptor(
common.EntityIDFromMetadataInterceptor(),
common.UserIDFromMetadataInterceptor(myUserIDKey),
),
)
func WithMountedEntityID ¶
WithMountedEntityID stores the entity ID in context. This is typically called by mount middleware after extracting the path parameter.
func WrapWithEntityExtraction ¶
WrapWithEntityExtraction wraps a handler with entity ID extraction middleware. This is a convenience function for routers that don't support middleware chaining.
Example:
mux.Handle("/songs/{songId}/likes/",
common.WrapWithEntityExtraction("songId", likesService.RESTHandler()))
Types ¶
type GatewayMuxOption ¶
type GatewayMuxOption func(*gatewayMuxConfig)
GatewayMuxOption configures a gRPC-gateway ServeMux for entity extraction.
func WithEntityParamToMetadata ¶
func WithEntityParamToMetadata(paramName string) GatewayMuxOption
WithEntityParamToMetadata configures the gateway to extract a path parameter and send it as gRPC metadata to the remote server.
Example:
mux := common.NewGatewayMux(common.WithEntityParamToMetadata("songId"))
likesv1.RegisterLikesServiceHandlerFromEndpoint(ctx, mux, grpcAddr, opts)
router.Handle("/songs/{songId}/likes/", mux)
func WithExtraMetadata ¶
WithExtraMetadata allows adding custom metadata extraction logic.
func WithUserParamToMetadata ¶
func WithUserParamToMetadata(paramName string) GatewayMuxOption
WithUserParamToMetadata configures the gateway to extract a user ID path parameter and send it as gRPC metadata.
type HandlerConfig ¶
type HandlerConfig struct {
// EntityParamName is the path parameter name that maps to entity_id.
// The router extracts this from the URL (e.g., "songId" from /songs/{songId}).
EntityParamName string
}
HandlerConfig configures how a service handler extracts entity context.
type HandlerOption ¶
type HandlerOption func(*HandlerConfig)
HandlerOption configures handler behavior.
func WithEntityParam ¶
func WithEntityParam(paramName string) HandlerOption
WithEntityParam specifies which router path parameter to use as entity_id. The mount wrapper will extract this parameter from the router's context (chi.URLParam, gorilla mux.Vars, or Go 1.22+ request.PathValue).
Example:
// Mount likes service at /songs/{songId}/likes
router.Handle("/songs/{songId}/likes/", likesService.RESTHandler(
common.WithEntityParam("songId"),
))
type MountedEntityContextKey ¶
type MountedEntityContextKey struct{}
MountedEntityContextKey is the context key for storing the entity ID extracted from the mount path parameter.