common

package
v0.7.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 6, 2026 License: Apache-2.0 Imports: 5 Imported by: 0

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

View Source
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

func EntityParamMiddleware(paramName string) func(http.Handler) http.Handler

EntityParamMiddleware returns middleware that extracts a path parameter and stores it as the mounted entity ID in context.

func ExtractPathParam

func ExtractPathParam(r *http.Request, name string) string

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

func GetEntityIDFromContextOrMetadata(ctx context.Context) string

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

func GetMountedEntityID(ctx context.Context) string

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

func WithMountedEntityID(ctx context.Context, entityID string) context.Context

WithMountedEntityID stores the entity ID in context. This is typically called by mount middleware after extracting the path parameter.

func WrapWithEntityExtraction

func WrapWithEntityExtraction(paramName string, handler http.Handler) http.Handler

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

func WithExtraMetadata(fn func(context.Context, *http.Request) metadata.MD) GatewayMuxOption

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL