Documentation
¶
Overview ¶
Package server defines the server lifecycle abstraction and concrete HTTP (gin) and gRPC servers, wired to service registration for graceful deregister-before-stop.
Index ¶
- func HTTPRouteNames() []string
- func NewGinEngine(opts *options.ServerOptions) (*gin.Engine, error)
- func RegisterHTTPRoute(name string, r HTTPRoute)
- func Serve(ctx context.Context, srv Server) error
- type ErrorRenderer
- type GRPCOption
- type GRPCServer
- type HTTPOption
- type HTTPRoute
- type HTTPServer
- type MeshServer
- type MeshServerOption
- type Method
- type Renderer
- type Route
- type RouteGroup
- func (g *RouteGroup) Apply(parent *gin.RouterGroup)
- func (g *RouteGroup) DELETE(path string, h gin.HandlerFunc) *RouteGroup
- func (g *RouteGroup) GET(path string, h gin.HandlerFunc) *RouteGroup
- func (g *RouteGroup) Group(prefix string, mws ...middleware.Middleware) *RouteGroup
- func (g *RouteGroup) HEAD(path string, h gin.HandlerFunc) *RouteGroup
- func (g *RouteGroup) Handle(method, path string, h gin.HandlerFunc) *RouteGroup
- func (g *RouteGroup) Name() string
- func (g *RouteGroup) OPTIONS(path string, h gin.HandlerFunc) *RouteGroup
- func (g *RouteGroup) PATCH(path string, h gin.HandlerFunc) *RouteGroup
- func (g *RouteGroup) POST(path string, h gin.HandlerFunc) *RouteGroup
- func (g *RouteGroup) PUT(path string, h gin.HandlerFunc) *RouteGroup
- func (g *RouteGroup) RouteGroups() []*RouteGroup
- func (g *RouteGroup) SetName(name string) *RouteGroup
- func (g *RouteGroup) Use(mws ...middleware.Middleware) *RouteGroup
- type Server
- type Service
- type ServiceEntry
- type ServiceGroup
- type ValidateHook
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func HTTPRouteNames ¶
func HTTPRouteNames() []string
HTTPRouteNames returns the sorted names of all registered route modules.
func NewGinEngine ¶
func NewGinEngine(opts *options.ServerOptions) (*gin.Engine, error)
NewGinEngine returns a gin engine with the unified middleware chain already applied, ready for the caller to register routes with the full gin API. The returned engine is accepted by MeshServer; a raw gin.New() is rejected there so middleware can never be silently bypassed.
func RegisterHTTPRoute ¶
RegisterHTTPRoute registers a route module under name. Business packages call this from init().
Types ¶
type ErrorRenderer ¶
ErrorRenderer writes a failed call. It has the same signature as codec.RenderError so the framework default can be named directly.
type GRPCOption ¶
type GRPCOption func(*GRPCServer)
GRPCOption configures a GRPCServer.
func WithGRPCRegistrar ¶
func WithGRPCRegistrar(r registry.Registrar, inst *registry.ServiceInstance) GRPCOption
WithGRPCRegistrar attaches a registrar and the instance to register on Start and deregister on Stop.
type GRPCServer ¶
type GRPCServer struct {
// contains filtered or unexported fields
}
GRPCServer is a grpc-go server with optional service registration.
func NewGRPCServer ¶
func NewGRPCServer(addr string, register func(grpc.ServiceRegistrar), opts ...grpc.ServerOption) *GRPCServer
NewGRPCServer creates a gRPC server. register is invoked with the server on Start to register business services.
func (*GRPCServer) WithRegistrar ¶
func (s *GRPCServer) WithRegistrar(r registry.Registrar, inst *registry.ServiceInstance) *GRPCServer
WithRegistrar is a fluent variant of WithGRPCRegistrar.
type HTTPOption ¶
type HTTPOption func(*HTTPServer)
HTTPOption configures an HTTPServer.
func WithRegistrar ¶
func WithRegistrar(r registry.Registrar, inst *registry.ServiceInstance) HTTPOption
WithRegistrar attaches a registrar and the instance to register on Start and deregister on Stop.
type HTTPRoute ¶
type HTTPRoute interface {
// Name is a stable identifier for the route module.
Name() string
// RouteGroups returns the module's declarative route groups.
RouteGroups() []*RouteGroup
}
HTTPRoute is a pluggable HTTP route module: it self-describes its name and declares its routes as RouteGroups (declarative data rather than imperative engine mutation). Business packages call RegisterHTTPRoute from init(); the composition root discovers them via AllHTTPRoutes(), so adding a route module no longer requires touching the composition root (open/closed principle), mirroring registry.Backend and middleware.Register. A *RouteGroup satisfies this interface directly, so the usual registration is a single group.
func AllHTTPRoutes ¶
func AllHTTPRoutes() []HTTPRoute
AllHTTPRoutes returns all registered route modules in sorted name order, for the composition root to assemble.
func GetHTTPRoute ¶
GetHTTPRoute returns the route module registered under name.
type HTTPServer ¶
type HTTPServer struct {
// contains filtered or unexported fields
}
HTTPServer is a gin-backed HTTP server with optional service registration.
func NewHTTPServer ¶
func NewHTTPServer(addr string, handler http.Handler, opts ...HTTPOption) *HTTPServer
NewHTTPServer creates an HTTP server serving the given handler.
type MeshServer ¶
type MeshServer struct {
// contains filtered or unexported fields
}
MeshServer is the facade for a onexmesh service instance. It aggregates the HTTP and gRPC servers, the unified middleware chain and the registry into a single runnable unit, and owns the runtime initialization (slog + OpenTelemetry) for the options it is built from. Configure it with the WithXxx options, then run it via Run; a concurrent or out-of-band shutdown is available via GracefulStop.
func NewMeshServer ¶
func NewMeshServer(opts *options.ServerOptions, mopts ...MeshServerOption) *MeshServer
NewMeshServer builds a MeshServer from the given options and configuration options. It does not initialize or serve anything; assembly and runtime initialization happen on Run.
func (*MeshServer) GracefulStop ¶
func (s *MeshServer) GracefulStop(ctx context.Context) error
GracefulStop gracefully stops the running service group by canceling its run context and waiting for Run's cleanup (including deregistration) to finish, honoring ctx timeout. It is safe to call before Run (no-op) or concurrently with Run.
func (*MeshServer) Options ¶
func (s *MeshServer) Options() *options.ServerOptions
Options returns the server options this instance was built from.
func (*MeshServer) Run ¶
func (s *MeshServer) Run(ctx context.Context) error
Run initializes the runtime capabilities (slog + OpenTelemetry), assembles the HTTP/gRPC service group, starts it and blocks until ctx is canceled or a server fails, then gracefully stops and deregisters the servers before returning. It mirrors onexstack's GenericAPIServer.Run contract, so its method value satisfies onexstack's app.RunFunc.
type MeshServerOption ¶
type MeshServerOption func(*MeshServer)
MeshServerOption configures a MeshServer.
func WithGRPCRegister ¶
func WithGRPCRegister(fn func(grpc.ServiceRegistrar)) MeshServerOption
WithGRPCRegister supplies a raw gRPC service registration callback (the generated RegisterXxxServer). Prefer WithService, which carries this for you.
func WithGinEngine ¶
func WithGinEngine(engine *gin.Engine) MeshServerOption
WithGinEngine supplies an externally-built gin engine (via NewGinEngine) so the caller can register native gin routes directly. Any WithService services are then applied on top of the engine's root router group.
func WithRoute ¶
func WithRoute(routes ...HTTPRoute) MeshServerOption
WithRoute appends native-gin HTTP route plugins (HTTPRoute). Useful for path/query/streaming endpoints with no proto definition.
func WithService ¶
func WithService(svcs ...Service) MeshServerOption
WithService appends proto-first services. Each Service declares both the gRPC registration (Service.Register) and the proto-first HTTP routes (Service.Methods), so one implementation serves both protocols.
type Method ¶
type Method struct {
// Name is the gRPC method name, e.g. "SayHello".
Name string
// Method is the HTTP verb, e.g. "GET".
Method string
// Path is the HTTP path template, e.g. "/helloworld/{name}".
Path string
// Body is the body binding: "*" for the whole message, "" for none.
Body string
// Status is the HTTP status a successful call returns. Zero means 200, so a
// Method built by NewMethod needs nothing set and existing generated code is
// unaffected.
//
// It exists because the status is not derivable from the verb. A contract that
// returns 201 for resource creation and 204 for deletion cannot be served by a
// fixed 200: the two are told apart by what the operation *means*, not by
// whether it is a POST. Set it from the contract, in the composition root,
// where the contract is already being read.
Status int
// Handler is the unified business logic, shared with gRPC.
Handler middleware.Handler
// Render renders a successful (non-nil) response. Nil means codec.Render,
// the framework's generic JSON/protobuf codec.
//
// It exists because the wire shape of a response is a decision the contract
// owns, not the transport. The generic codec marshals the generated Go struct
// with encoding/json, which drops zero-valued fields and emits a
// google.protobuf.Timestamp as {"seconds":...}: fine for a debug endpoint,
// wrong for a contract that requires zero values to appear and timestamps as
// RFC3339. Leaving it nil keeps the current behaviour, so existing generated
// code is unaffected.
Render Renderer
// RenderError renders a failed call. Nil means codec.RenderError, the
// framework's errorsx envelope ({"code":<http status>,"reason":...}).
//
// It is a separate hook because the two shapes are separately owned: a
// contract that documents {"code":"Domain.Specific"} — a string reason, no
// numeric status in the body — cannot be served by the errorsx envelope, and
// answering the wrong one is invisible to a client that only checks the HTTP
// status.
RenderError ErrorRenderer
// Validate applies the request's default values and runs its validation. It
// is called after the request is bound from path/query/body and before the
// handler sees it, which is the only point where both hold: before binding
// there is no message to default, and after the handler the request may
// already have been written.
//
// It exists because binding and judging are different jobs with different
// owners. The framework knows how to turn a request into a message; whether
// the message means anything — a size a caller may ask for, a field the
// contract requires, a name that is already taken — is the contract's
// business, and it is the same judgement for every transport. Leaving it nil
// keeps the current behaviour, so existing generated code is unaffected.
Validate ValidateHook
// contains filtered or unexported fields
}
Method declares one proto RPC method's HTTP surface. It is a data descriptor: Path carries the grpc-gateway-style "{field}" template, Body the body binding ("" or "*"), newReq the proto-first request factory and Handler the business logic. The composition root turns it into a gin route via httpHandler.
func NewMethod ¶
func NewMethod[Req, Resp proto.Message]( name, method, path, body string, h func(context.Context, Req) (Resp, error), ) Method
NewMethod builds a proto-first Method from a strongly-typed business function h. The Req/Resp type parameters are constrained to proto.Message, so request and response types are enforced to be protobuf at compile time, and the same h backs both the gRPC method (via the generated RegisterXxxServer) and the HTTP route (via httpHandler).
NewMethod derives the request factory from Req, so a caller never passes one: a constructor closure would restate what h's signature already says, and the only shape it can usefully take is "allocate a zero Req". Inference runs from h alone, so the generated call is
server.NewMethod("SayHello", "GET", "/helloworld/{name}", "", srv.SayHello)
func (Method) Apply ¶
func (m Method) Apply(g *gin.RouterGroup)
Apply registers the Method's HTTP route onto g.
func (Method) StatusOrDefault ¶
StatusOrDefault returns the status a successful call returns, defaulting to 200 for a Method that declares none.
type Renderer ¶
Renderer writes a successful response. It has the same signature as codec.Render so the framework default can be named directly.
type Route ¶
type Route struct {
// Method is the HTTP verb, e.g. http.MethodGet.
Method string
// Path is the gin route template, e.g. "/users/:id".
Path string
// GinHandler is the native gin handler for path/query/streaming cases.
GinHandler gin.HandlerFunc
}
Route declares a single native-gin HTTP endpoint as data rather than behavior. RouteGroup's fluent verbs build these for you; construct one directly only for the rare case of a pre-built route list. Proto-first body-based endpoints belong in Service.Method instead.
func NewGinRoute ¶
func NewGinRoute(method, path string, h gin.HandlerFunc) Route
NewGinRoute builds a native gin Route for the path/query/streaming cases.
type RouteGroup ¶
type RouteGroup struct {
// contains filtered or unexported fields
}
RouteGroup is a fluent, declarative HTTP route group. It mirrors gin's RouterGroup chaining — Group / Use / GET / POST / ... — but instead of mutating a gin engine it records routes as data, so the composition root assembles the engine in one place. A RouteGroup satisfies HTTPRoute, so it can be registered directly via RegisterHTTPRoute.
func NewGroup ¶
func NewGroup(prefix string, mws ...middleware.Middleware) *RouteGroup
NewGroup returns a route group under the given path prefix and group-level middleware. An empty prefix registers routes at the parent's root.
func (*RouteGroup) Apply ¶
func (g *RouteGroup) Apply(parent *gin.RouterGroup)
Apply registers the group, its routes and its nested children onto parent.
func (*RouteGroup) DELETE ¶
func (g *RouteGroup) DELETE(path string, h gin.HandlerFunc) *RouteGroup
DELETE registers a native gin DELETE route and returns g.
func (*RouteGroup) GET ¶
func (g *RouteGroup) GET(path string, h gin.HandlerFunc) *RouteGroup
GET registers a native gin GET route and returns g.
func (*RouteGroup) Group ¶
func (g *RouteGroup) Group(prefix string, mws ...middleware.Middleware) *RouteGroup
Group creates a nested child group under the given relative prefix and returns it, mirroring gin's RouterGroup.Group.
func (*RouteGroup) HEAD ¶
func (g *RouteGroup) HEAD(path string, h gin.HandlerFunc) *RouteGroup
HEAD registers a native gin HEAD route and returns g.
func (*RouteGroup) Handle ¶
func (g *RouteGroup) Handle(method, path string, h gin.HandlerFunc) *RouteGroup
Handle registers a native gin route for an arbitrary method and returns g.
func (*RouteGroup) Name ¶
func (g *RouteGroup) Name() string
Name returns the group's self-descriptive name, set via SetName.
func (*RouteGroup) OPTIONS ¶
func (g *RouteGroup) OPTIONS(path string, h gin.HandlerFunc) *RouteGroup
OPTIONS registers a native gin OPTIONS route and returns g.
func (*RouteGroup) PATCH ¶
func (g *RouteGroup) PATCH(path string, h gin.HandlerFunc) *RouteGroup
PATCH registers a native gin PATCH route and returns g.
func (*RouteGroup) POST ¶
func (g *RouteGroup) POST(path string, h gin.HandlerFunc) *RouteGroup
POST registers a native gin POST route and returns g.
func (*RouteGroup) PUT ¶
func (g *RouteGroup) PUT(path string, h gin.HandlerFunc) *RouteGroup
PUT registers a native gin PUT route and returns g.
func (*RouteGroup) RouteGroups ¶
func (g *RouteGroup) RouteGroups() []*RouteGroup
RouteGroups returns g itself, satisfying the HTTPRoute interface.
func (*RouteGroup) SetName ¶
func (g *RouteGroup) SetName(name string) *RouteGroup
SetName sets the group's self-descriptive name and returns g for chaining.
func (*RouteGroup) Use ¶
func (g *RouteGroup) Use(mws ...middleware.Middleware) *RouteGroup
Use appends group-level middleware and returns g for chaining.
type Server ¶
type Server interface {
// Start runs the server and blocks until it stops or errors. A graceful
// stop returns nil.
Start(ctx context.Context) error
// Stop gracefully shuts the server down, honoring ctx timeout.
Stop(ctx context.Context) error
}
Server is the unified lifecycle for all servers (HTTP/gRPC).
type Service ¶
type Service struct {
// Name is the service name, e.g. "helloworld.Greeter".
Name string
// Register registers the gRPC business service (the generated
// RegisterXxxServer, or additional streaming services). Nil disables gRPC.
Register func(grpc.ServiceRegistrar)
// Methods declares the proto-first HTTP routes; each Method's Handler is the
// same strongly-typed function the gRPC service exposes.
Methods []Method
// RouteGroups declares native-gin HTTP routes (path/query params, no proto).
RouteGroups []*RouteGroup
}
Service declares a business service served over gRPC and/or HTTP. A single proto service produces one Service: its gRPC methods are registered via Register (the generated RegisterXxxServer plus any streaming services), and its HTTP routes are declared as proto-first Methods whose request/response types are enforced to be protobuf messages at compile time. RouteGroups is the native-gin escape hatch for pure-HTTP path/query cases with no proto definition. Protocol gating (grpc | http | both) happens in the composition root via opts.Mesh.Protocol.
func NewService ¶
NewService builds a Service from a set of proto-first Methods.
type ServiceEntry ¶
ServiceEntry couples a name with a Server for lifecycle management.
type ServiceGroup ¶
type ServiceGroup struct {
// contains filtered or unexported fields
}
ServiceGroup manages a set of servers: they start concurrently and stop in reverse registration order (later-started services stop first), following the go-zero ServiceGroup convention.
func NewServiceGroup ¶
func NewServiceGroup() *ServiceGroup
NewServiceGroup creates an empty ServiceGroup.
func (*ServiceGroup) Add ¶
func (g *ServiceGroup) Add(name string, s Server)
Add appends a server to the group.