Documentation
¶
Overview ¶
Package goichi is a multi-protocol web API framework for Go.
A single App can serve REST, WebSocket, GraphQL, gRPC, ConnectRPC, MQTT and MCP, optionally multiplexed onto one TCP port, behind one middleware chain and one JWT configuration.
Getting started ¶
app := goichi.New(goichi.Config{})
app.GET("/hello/:name", func(c *goichi.Context) error {
return c.JSON(map[string]string{"message": "Hello, " + c.Param("name")})
})
app.Listen(":3000")
Routing ¶
Paths may contain ":name" parameters and a trailing "*rest" catch-all. Static segments win over parameters, which win over the catch-all. By default the router ignores a trailing slash and matches literal segments without regard to ASCII case; see RoutingConfig. Parameter values always keep their original casing.
Requests to a known path with an unregistered method receive 405 together with an Allow header, and OPTIONS is answered automatically, so CORS preflight works without declaring OPTIONS routes.
Middleware ¶
Middleware is a func(Handler) Handler. Register it globally with App.Use, per group, or per route. The route table is compiled once before the first request, so Use may be called after the routes it should wrap have been declared.
middleware.Recover and middleware.SecurityHeaders are installed by default: fasthttp does not recover panics on its own, and an escaping panic would take down the process rather than the request.
Authentication ¶
Setting Config.JWT.Secret enables the same HS256 verification for every protocol at once. Individual routes opt out with Route.NoAuth; the built-in docs, favicon and health endpoints already do.
Protocols ¶
Protocol servers are registered with App.RegisterProtocol and started with the app. With Config.Server.EnablePortMultiplexing the HTTP-based protocols share the main port. MQTT and MCP always listen on their own port: MCP speaks JSON-RPC over raw TCP and is never mounted on the HTTP router.
Index ¶
- Constants
- func B64Encode(s string) string
- func ErrBadRequest(c *core.Context, msg string) error
- func ErrForbidden(c *core.Context) error
- func ErrInternal(c *core.Context) error
- func ErrNotFound(c *core.Context, entity string) error
- func ErrUnauthorized(c *core.Context) error
- func ErrValidation(c *core.Context, ve *core.ValidationError) error
- func Send(c *core.Context, data any) error
- func SendCreated(c *core.Context, data any) error
- func SendPage(c *core.Context, items any, page, perPage, total int) error
- type App
- func (a *App) ANY(path string, h Handler, m ...Middleware) Routes
- func (a *App) AddDocs(config DocsConfig)
- func (a *App) DELETE(path string, h Handler, m ...Middleware) *Route
- func (a *App) EnableHealthCheck(path string)
- func (a *App) GET(path string, h Handler, m ...Middleware) *Route
- func (a *App) GetProtocols() *protocol.ProtocolRegistry
- func (a *App) GetRoutes() []*RouteInfo
- func (a *App) Group(prefix string, m ...Middleware) *Group
- func (a *App) IsMaster() bool
- func (a *App) Listen(addr string) error
- func (a *App) ListenGraceful(addr string) error
- func (a *App) OnShutdown(f ...func())
- func (a *App) PATCH(path string, h Handler, m ...Middleware) *Route
- func (a *App) POST(path string, h Handler, m ...Middleware) *Route
- func (a *App) PUT(path string, h Handler, m ...Middleware) *Route
- func (a *App) RegisterProtocol(handler protocol.ProtocolHandler)
- func (a *App) SetErrorHandler(handler core.ErrorHandler)
- func (a *App) SetJWTAuth(cfg middleware.JWTConfig)
- func (a *App) StartAllProtocols(ctx context.Context) error
- func (a *App) StartProtocols(ctx context.Context, names ...string) error
- func (a *App) StopAllProtocols(ctx context.Context) error
- func (a *App) Use(m ...Middleware)
- func (a *App) UseAll(m ...Middleware)
- func (a *App) UseGRPCStream(i ...grpc.StreamServerInterceptor)
- func (a *App) UseGRPCUnary(i ...grpc.UnaryServerInterceptor)
- func (a *App) UseProtocol(m ...ProtocolFastHTTPMiddleware)
- func (a *App) UseUnified(m ...UnifiedMiddleware)
- func (a *App) ValidateConfig() error
- type Config
- type Context
- type DocsConfig
- type Group
- func (g *Group) ANY(path string, h Handler, m ...Middleware) Routes
- func (g *Group) DELETE(path string, h Handler, m ...Middleware) *Route
- func (g *Group) GET(path string, h Handler, m ...Middleware) *Route
- func (g *Group) Group(prefix string, m ...Middleware) *Group
- func (g *Group) PATCH(path string, h Handler, m ...Middleware) *Route
- func (g *Group) POST(path string, h Handler, m ...Middleware) *Route
- func (g *Group) PUT(path string, h Handler, m ...Middleware) *Route
- func (g *Group) Static(prefix, root string)
- type Handler
- type Middleware
- type Pagination
- type ProtocolFastHTTPMiddleware
- type Route
- type RouteInfo
- type RouteOption
- type Router
- func (r *Router) ANY(path string, h Handler, m ...Middleware) Routes
- func (r *Router) Build()
- func (r *Router) DELETE(path string, h Handler, m ...Middleware) *Route
- func (r *Router) EnableDocs(path string, htmlContent string)
- func (r *Router) GET(path string, h Handler, m ...Middleware) *Route
- func (r *Router) HandleRequest(ctx *fasthttp.RequestCtx)
- func (r *Router) PATCH(path string, h Handler, m ...Middleware) *Route
- func (r *Router) POST(path string, h Handler, m ...Middleware) *Route
- func (r *Router) PUT(path string, h Handler, m ...Middleware) *Route
- func (r *Router) Static(prefix, root string)
- func (r *Router) Use(m ...Middleware)
- type Routes
- type RoutingConfig
- type ServerConfig
- type UnifiedMiddleware
- type ValidationError
Constants ¶
const ( // 2xx Success StatusOK = core.StatusOK StatusCreated = core.StatusCreated StatusAccepted = core.StatusAccepted StatusNonAuthoritativeInfo = core.StatusNonAuthoritativeInfo StatusNoContent = core.StatusNoContent StatusResetContent = core.StatusResetContent StatusPartialContent = core.StatusPartialContent // 3xx Redirection StatusMultipleChoices = core.StatusMultipleChoices StatusMovedPermanently = core.StatusMovedPermanently StatusFound = core.StatusFound StatusSeeOther = core.StatusSeeOther StatusNotModified = core.StatusNotModified StatusTemporaryRedirect = core.StatusTemporaryRedirect StatusPermanentRedirect = core.StatusPermanentRedirect // 4xx Client errors StatusBadRequest = core.StatusBadRequest StatusPaymentRequired = core.StatusPaymentRequired StatusForbidden = core.StatusForbidden StatusNotFound = core.StatusNotFound StatusMethodNotAllowed = core.StatusMethodNotAllowed StatusNotAcceptable = core.StatusNotAcceptable StatusProxyAuthRequired = core.StatusProxyAuthRequired StatusRequestTimeout = core.StatusRequestTimeout StatusConflict = core.StatusConflict StatusGone = core.StatusGone StatusLengthRequired = core.StatusLengthRequired StatusPreconditionFailed = core.StatusPreconditionFailed StatusRequestEntityTooLarge = core.StatusRequestEntityTooLarge StatusRequestURITooLong = core.StatusRequestURITooLong StatusUnsupportedMediaType = core.StatusUnsupportedMediaType StatusRequestedRangeNotSatisfiable = core.StatusRequestedRangeNotSatisfiable StatusExpectationFailed = core.StatusExpectationFailed StatusTeapot = core.StatusTeapot StatusUnprocessableEntity = core.StatusUnprocessableEntity StatusLocked = core.StatusLocked StatusFailedDependency = core.StatusFailedDependency StatusUpgradeRequired = core.StatusUpgradeRequired StatusPreconditionRequired = core.StatusPreconditionRequired StatusTooManyRequests = core.StatusTooManyRequests StatusHeaderFieldsTooLarge = core.StatusHeaderFieldsTooLarge // 5xx Server errors StatusInternalServerError = core.StatusInternalServerError StatusNotImplemented = core.StatusNotImplemented StatusBadGateway = core.StatusBadGateway StatusGatewayTimeout = core.StatusGatewayTimeout StatusHTTPVersionNotSupported = core.StatusHTTPVersionNotSupported StatusVariantAlsoNegotiates = core.StatusVariantAlsoNegotiates StatusInsufficientStorage = core.StatusInsufficientStorage StatusLoopDetected = core.StatusLoopDetected StatusNotExtended = core.StatusNotExtended StatusNetworkAuthenticationRequired = core.StatusNetworkAuthenticationRequired )
HTTP status codes, re-exported from the core package so applications only need to import goichi.
Variables ¶
This section is empty.
Functions ¶
func ErrForbidden ¶
func ErrInternal ¶
func ErrUnauthorized ¶
func ErrValidation ¶
func ErrValidation(c *core.Context, ve *core.ValidationError) error
Types ¶
type App ¶
type App struct {
Router *Router
Config Config
Registry *protocol.ProtocolRegistry
// contains filtered or unexported fields
}
App is a configured application: a router, a set of protocol servers and the middleware shared between them. Create one with New.
func New ¶
New returns an App configured by config, with panic recovery and security headers already installed. When config.JWT.Secret is set, unified JWT auth is enabled for every protocol.
func (*App) ANY ¶
func (a *App) ANY(path string, h Handler, m ...Middleware) Routes
ANY registers the same handler for every common HTTP method.
func (*App) AddDocs ¶
func (a *App) AddDocs(config DocsConfig)
AddDocs registers an additional documentation page, letting one app expose several filtered views of its API.
func (*App) DELETE ¶
func (a *App) DELETE(path string, h Handler, m ...Middleware) *Route
DELETE registers a handler for DELETE requests to path.
func (*App) EnableHealthCheck ¶
EnableHealthCheck registers a plain-text liveness endpoint. It is exempt from unified JWT auth so probes do not need a token.
func (*App) GET ¶
func (a *App) GET(path string, h Handler, m ...Middleware) *Route
GET registers a handler for GET requests to path.
func (*App) GetProtocols ¶
func (a *App) GetProtocols() *protocol.ProtocolRegistry
func (*App) Group ¶
func (a *App) Group(prefix string, m ...Middleware) *Group
Group returns a route group sharing a path prefix and middleware.
func (*App) IsMaster ¶
IsMaster reports whether this is the parent process, which is always true unless multiprocess mode spawned it as a child.
func (*App) Listen ¶
Listen binds addr and serves every registered protocol until the process receives SIGINT or SIGTERM.
func (*App) ListenGraceful ¶
ListenGraceful binds addr like Listen, and additionally supports the multiprocess model configured by ServerConfig.Multiprocess.
func (*App) OnShutdown ¶
func (a *App) OnShutdown(f ...func())
OnShutdown registers functions to run after the server stops accepting connections.
func (*App) PATCH ¶
func (a *App) PATCH(path string, h Handler, m ...Middleware) *Route
PATCH registers a handler for PATCH requests to path.
func (*App) POST ¶
func (a *App) POST(path string, h Handler, m ...Middleware) *Route
POST registers a handler for POST requests to path.
func (*App) PUT ¶
func (a *App) PUT(path string, h Handler, m ...Middleware) *Route
PUT registers a handler for PUT requests to path.
func (*App) RegisterProtocol ¶
func (a *App) RegisterProtocol(handler protocol.ProtocolHandler)
RegisterProtocol adds a protocol server to the app. It inherits the unified auth configuration and the middleware registered with UseProtocol.
func (*App) SetErrorHandler ¶
func (a *App) SetErrorHandler(handler core.ErrorHandler)
SetErrorHandler replaces the default handler for errors returned by routes.
func (*App) SetJWTAuth ¶
func (a *App) SetJWTAuth(cfg middleware.JWTConfig)
SetJWTAuth installs one JWT configuration for every protocol. Routes marked with Route.NoAuth are exempt; so are the built-in docs, favicon and health endpoints.
func (*App) StartProtocols ¶
func (*App) Use ¶
func (a *App) Use(m ...Middleware)
Use registers middleware for every route, including routes declared earlier.
func (*App) UseAll ¶
func (a *App) UseAll(m ...Middleware)
UseAll registers middleware for the router and for every protocol server.
func (*App) UseGRPCStream ¶
func (a *App) UseGRPCStream(i ...grpc.StreamServerInterceptor)
func (*App) UseGRPCUnary ¶
func (a *App) UseGRPCUnary(i ...grpc.UnaryServerInterceptor)
func (*App) UseProtocol ¶
func (a *App) UseProtocol(m ...ProtocolFastHTTPMiddleware)
func (*App) UseUnified ¶
func (a *App) UseUnified(m ...UnifiedMiddleware)
func (*App) ValidateConfig ¶
ValidateConfig checks the application configuration for required fields and potential misconfigurations (fail-fast).
type Config ¶
type Config struct {
Server ServerConfig
Routing RoutingConfig
Docs DocsConfig
JWT middleware.JWTConfig
// Security is the default security scheme advertised in generated docs.
Security openapi.SecurityScheme
}
Config is the application configuration passed to New.
type DocsConfig ¶
type DocsConfig struct {
Enable bool
Path string
Title string
Desc string
PageTitle string
DarkMode bool
ScalarJSURL string
Security openapi.SecurityScheme
Filter func(*RouteInfo) bool
}
DocsConfig describes one generated OpenAPI reference page.
type Group ¶
type Group struct {
// contains filtered or unexported fields
}
type Middleware ¶
type Middleware = core.Middleware
type Pagination ¶
type Pagination = core.Pagination
type ProtocolFastHTTPMiddleware ¶
type ProtocolFastHTTPMiddleware func(next fasthttp.RequestHandler) fasthttp.RequestHandler
func MiddlewareAsProtocol ¶
func MiddlewareAsProtocol(m Middleware) ProtocolFastHTTPMiddleware
type Route ¶
type Route struct {
// contains filtered or unexported fields
}
func (*Route) ContentType ¶
func (*Route) RequestModel ¶
func (*Route) ResponseModel ¶
type RouteInfo ¶
type RouteInfo struct {
Method string
Path string
Summary string
Tags []string
ResponseModel any
RequestModel any
NoAuth bool
HideDoc bool
ContentType string
}
RouteInfo is the metadata describing a single registered route.
type RouteOption ¶
type RouteOption func(*RouteInfo)
func WithRequest ¶
func WithRequest(model any) RouteOption
func WithResponse ¶
func WithResponse(model any) RouteOption
func WithSummary ¶
func WithSummary(s string) RouteOption
func WithTags ¶
func WithTags(tags ...string) RouteOption
type Router ¶
type Router struct {
// Routes describes every registered route. It backs the generated OpenAPI
// document and is safe to read after registration.
Routes []*RouteInfo
// ErrorHandler, when set, receives any error returned by a handler.
ErrorHandler core.ErrorHandler
// StrictSlash distinguishes "/users" from "/users/" when true. When false
// (the default) a trailing slash is ignored.
StrictSlash bool
// CaseSensitive matches literal path segments exactly when true. When false
// (the default) "/Users" also matches a "/users" route. Parameter values
// always keep their original casing.
CaseSensitive bool
// contains filtered or unexported fields
}
Router matches incoming requests against a radix tree per HTTP method and invokes the registered handler.
Handlers are not composed with their middleware at registration time. The whole table is compiled once, on the first request or on an explicit Build call, so that middleware registered with Use after a route was declared still applies to it.
func NewRouter ¶
NewRouter returns a Router. See Router.StrictSlash and Router.CaseSensitive for the meaning of the two flags.
func (*Router) ANY ¶
func (r *Router) ANY(path string, h Handler, m ...Middleware) Routes
ANY registers the same handler for every common HTTP method.
func (*Router) Build ¶
func (r *Router) Build()
Build compiles the route table. It is called automatically before the first request; calling it earlier surfaces registration problems at startup.
func (*Router) DELETE ¶
func (r *Router) DELETE(path string, h Handler, m ...Middleware) *Route
DELETE registers a handler for DELETE requests to path.
func (*Router) EnableDocs ¶
EnableDocs serves a static HTML page at path.
func (*Router) GET ¶
func (r *Router) GET(path string, h Handler, m ...Middleware) *Route
GET registers a handler for GET requests to path.
func (*Router) HandleRequest ¶
func (r *Router) HandleRequest(ctx *fasthttp.RequestCtx)
HandleRequest is the fasthttp entry point for the router.
func (*Router) PATCH ¶
func (r *Router) PATCH(path string, h Handler, m ...Middleware) *Route
PATCH registers a handler for PATCH requests to path.
func (*Router) POST ¶
func (r *Router) POST(path string, h Handler, m ...Middleware) *Route
POST registers a handler for POST requests to path.
func (*Router) PUT ¶
func (r *Router) PUT(path string, h Handler, m ...Middleware) *Route
PUT registers a handler for PUT requests to path.
func (*Router) Use ¶
func (r *Router) Use(m ...Middleware)
Use registers global middleware. Unlike most routers, Use may be called after routes have been declared; the middleware still applies to them.
type Routes ¶
type Routes []*Route
func (Routes) ContentType ¶
func (Routes) RequestModel ¶
func (Routes) ResponseModel ¶
type RoutingConfig ¶
type RoutingConfig struct {
// StrictSlash treats "/users" and "/users/" as different routes.
StrictSlash bool
// CaseSensitive matches literal path segments exactly. When false (the
// default) "/Users" also reaches a "/users" route; parameter values keep
// their original casing either way.
CaseSensitive bool
}
RoutingConfig tunes how request paths are matched.
type ServerConfig ¶
type ServerConfig struct {
AppName string
Multiprocess bool
NumChildren int
ShowStartup *bool
StartupBanner string
EnablePortMultiplexing bool
ReadTimeout time.Duration
WriteTimeout time.Duration
IdleTimeout time.Duration
MaxRequestBodySize int
// TLSCertFile and TLSKeyFile, when both set, serve the main HTTP listener
// over TLS (https). Leave empty when TLS is terminated upstream.
TLSCertFile string
TLSKeyFile string
}
ServerConfig controls the HTTP listener and process model.
func (*ServerConfig) SetDefaults ¶
func (c *ServerConfig) SetDefaults()
SetDefaults fills in the timeouts, body limit and application name that were left at their zero value.
func (*ServerConfig) TLSEnabled ¶
func (c *ServerConfig) TLSEnabled() bool
TLSEnabled reports whether both a certificate and key were configured for the main HTTP listener.
type UnifiedMiddleware ¶
type UnifiedMiddleware interface {
ToHTTP() ProtocolFastHTTPMiddleware
ToGRPCUnary() grpc.UnaryServerInterceptor
ToGRPCStream() grpc.StreamServerInterceptor
}
UnifiedMiddleware defines a middleware that can be applied to both HTTP and gRPC protocols.
type ValidationError ¶
type ValidationError = core.ValidationError