Documentation
¶
Index ¶
Constants ¶
const ( // MiddlewareTag is a struct tag key used to specify a single middleware name. MiddlewareTag = "middleware" // MiddlewaresTag is a struct tag key used to specify a comma-separated list of middleware names. MiddlewaresTag = "middlewares" // GroupTag is a struct tag key used to specify the group path prefix for routes. GroupTag = "group" // RouteTag is a struct tag key used to define the route's HTTP method and path. RouteTag = "route" )
Variables ¶
var ( // ErrTerminating is returned when attempting to start a new task after // the shutdown process has already been initiated. Once the tracker // begins terminating, no new tasks can be registered. ErrTerminating = errors.New("received terminating signal") // ErrTaskTrackerNotFound is returned when the specified task tracker cannot be located or does not exist. ErrTaskTrackerNotFound = errors.New("task tracker not found") )
var ( ErrTaskTrackerNotSet = errors.New("task tracker is not set") ErrLoggerNotSet = errors.New("logger is not set") ErrShutdown = casual.NewHTTPErrorFromMessage(503, "server is shutting down") )
Functions ¶
func AddLogFieldToAccessLog ¶
Types ¶
type Engine ¶
Engine defines the interface for an HTTP engine capable of registering routes, groups, and middleware and running the server. Implementations should integrate with a Gin engine.
Methods: - flatHandlers([]*Handler): Process a collection of Handler objects to flatten their routes, groups, and middleware. - applyHandlers(): Apply all collected routes, groups, and middleware to the underlying Gin engine. - Run(addr string) chan error: Run the HTTP server at the specified address and return a channel for errors.
func New ¶
New creates a new Engine (core implementation) given a list of Handler objects and optional parameters. Handlers usually come from the logic of `NewHandler` (not shown here), which reflectively extracts routes, groups, and middleware from a user-defined struct.
Parameters: - handlers: A slice of Handler objects containing routes, groups, and middleware definitions. - opts: A list of options (param functions) that configure the engine (e.g., setting a custom Gin instance or logger).
Returns: - Engine: a configured engine ready to register routes and run. - error: If any configuration step fails, an error is returned.
Example usage: ```go engine, err := New([]*Handler{handler1, handler2}, WithCustomLogger(myLogger))
if err != nil {
log.Fatal(err)
}
err := engine.Run(":8080") // waiting for error ```
type Group ¶
type Group struct {
Path string
// contains filtered or unexported fields
}
Group defines a group of routes that share a common path prefix and possibly a set of middlewares.
Fields: - `name`: The group's name, derived from the field name (e.g., "v3" from "V3"). - `Path`: The prefix path for all routes in this group (e.g., "/api/v3"). - `Middlewares`: A list of middleware names applied to all routes in the group.
**Example:**
```go
type IV3Group struct {
V3 Group `group:"/api/v3"`
}
type V3GroupImpl struct {
IV3Group
}
```
All routes referencing `group:"v3"` will be placed under "/api/v3".
type Handler ¶
type Handler struct {
// contains filtered or unexported fields
}
Handler processes a given handler struct to extract and configure routes, groups, and middlewares. It uses reflection to parse struct tags and associates them with the actual Gin handler functions.
The workflow is as follows: 1. Recursively scan the provided struct (including embedded and nested structs) for fields of type `Route`, `Group`, and `Middleware`. 2. Extract corresponding tags (e.g. `route:"POST /checkout/apply"`) to determine routes, their HTTP methods, paths, and middleware associations. 3. Match field names with struct methods (signature `func(*gin.Context)`) to create fully configured routes and middleware. 4. Store all parsed routes, groups, and middleware for later registration in a Gin router.
**Example:**
Consider a scenario in an online store application. We might have a versioned API group (`/api/v3`) and routes for products, cart, and checkout processes.
For example, define a group for version 3 of our API:
```go
type IV3Group struct {
V3 Group `group:"/api/v3"`
}
type V3GroupImpl struct {
IV3Group
}
```
Now, inside this versioned group, we could define product routes:
```go
type IProductRoutes struct {
ListProducts Route `route:"GET /products" middlewares:"auth,logging" group:"v3"`
GetProduct Route `route:"GET /products/:id" group:"v3"`
}
type ProductRoutesImpl struct {
IProductRoutes
}
func (p *ProductRoutesImpl) ListProducts(ctx *gin.Context) {
// Handler logic for listing products
// e.g., ctx.JSON(http.StatusOK, productList)
}
func (p *ProductRoutesImpl) GetProduct(ctx *gin.Context) {
// Handler logic for getting a single product by ID
// e.g., product := findProductByID(ctx.Param("id"))
// ctx.JSON(http.StatusOK, product)
}
```
We can also define middleware and checkout routes that use these middlewares:
```go
type ICheckoutRouter struct {
ApplyCart Route `route:"POST /checkout/apply" middlewares:"log,cors,analytics" group:"v3"`
LogMiddleware Middleware `middleware:"log"`
CorsMiddleware Middleware `middleware:"cors"`
AnalyticsMiddleware Middleware `middleware:"analytics"`
}
type CheckoutRouterImpl struct {
ICheckoutRouter
}
func (c *CheckoutRouterImpl) ApplyCart(ctx *gin.Context) {
// Handler logic for applying cart items to the checkout process
// e.g., ctx.JSON(http.StatusOK, checkoutResponse)
}
// Middleware example methods:
func (c *CheckoutRouterImpl) LogMiddleware(ctx *gin.Context) {
// Logging middleware logic
ctx.Next()
}
func (c *CheckoutRouterImpl) CorsMiddleware(ctx *gin.Context) {
// CORS middleware logic (set headers, etc.)
ctx.Next()
}
func (c *CheckoutRouterImpl) AnalyticsMiddleware(ctx *gin.Context) {
// Analytics middleware logic (track requests)
ctx.Next()
}
```
By creating a `Handler` with these structures, you can automatically discover and set up all routes, groups, and middleware:
```go handler := NewHandler(&CheckoutRouterImpl{}) // handler now includes all defined routes and associated middleware within the V3 group. ```
func AsHandler ¶
AsHandler creates a new Handler by analyzing the provided `handlerStruct`. It recursively extracts all methods and fields, builds routes, groups, and middleware, and returns a fully initialized Handler instance.
**Example:** Given `CheckoutRouterImpl` and `ProductRoutesImpl` as in the examples above, you could do:
```go handler := AsHandler(&ProductRoutesImpl{}) // The handler now holds routes like GET /api/v3/products (with auth, logging middleware), // and GET /api/v3/products/:id, ready to be registered in your Gin engine. ```
func NewAccessLogMiddleware ¶
func NewTaskTrackerMiddleware ¶
func NewTaskTrackerMiddleware(log Logger, tt TaskTracker) (*Handler, error)
type Logger ¶
type Logger interface {
Info(message string, args ...any)
Debug(message string, args ...any)
Error(message string, args ...any)
Panic(message string, args ...any)
Warn(message string, args ...any)
}
func NewFmtLogger ¶
func NewFmtLogger() Logger
type Middleware ¶
type Middleware struct {
// contains filtered or unexported fields
}
Middleware defines a middleware associated with a handler function and possibly other nested middlewares.
Fields: - `middleware`: The primary middleware name (from `middleware:"name"` tag or derived from the field name). - `middlewares`: A list of additional middleware names that this middleware applies internally. - `handler`: The Gin handler function for the middleware.
**Example:** ```go
type ICheckoutRouter struct {
ApplyCart Route `route:"POST /checkout/apply" middlewares:"log,cors,analytics" group:"v3"`
LogMiddleware Middleware `middleware:"log"`
CorsMiddleware Middleware `middleware:"cors"`
AnalyticsMiddleware Middleware `middleware:"analytics"`
}
```
Here, the `ApplyCart` route will be executed with the "log", "cors", and "analytics" middleware in the defined order.
type ParamsCb ¶
type ParamsCb func(*params) error
func WithGinEngine ¶
func WithLogger ¶
func WithRootMiddlewares ¶
func WithShutdownTimeout ¶
func WithTaskTracker ¶
func WithTaskTracker(tracker ...TaskTracker) ParamsCb
type Route ¶
type Route struct {
// contains filtered or unexported fields
}
Route defines an HTTP endpoint with a method, path, associated handler, and optional middlewares or group prefix.
Fields: - `method`: The HTTP method (e.g., "GET", "POST"). - `path`: The HTTP path (e.g., "/checkout/apply"). - `handler`: The Gin handler function that processes the request. - `middlewares`: A list of middleware names applied before the handler. - `group`: The name of the group this route belongs to, if any.
**Example:** ```go
type IProductRoutes struct {
ListProducts Route `route:"GET /products" middlewares:"auth,logging" group:"v3"`
}
``` This defines a GET route at `/api/v3/products` that applies "auth" and "logging" middleware.
type TaskTracker ¶
type TaskTracker interface {
StartTask() error
FinishTask()
TaskCount() int32
Shutdown(ctx context.Context) error
}
func GetTaskTracker ¶
func GetTaskTracker(ctx *gin.Context) (TaskTracker, error)
GetTaskTracker retrieves the activeTaskTracker instance from the gin.Context. Returns an error if task tracker is not provided
func NewActiveTaskTracker ¶
func NewActiveTaskTracker() TaskTracker
NewActiveTaskTracker creates and returns a new TaskTracker impl. By default, it starts with zero active tasks and a background context that can be canceled when shutdown is initiated.
Example usage:
tracker := NewActiveTaskTracker()
// Start a new task
if err := tracker.StartTask(); err == nil {
go func() {
// Do some work...
defer tracker.FinishTask()
}()
}
// Once you decide to stop the application:
tracker.Shutdown() // Blocks until all tasks have finished.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
examples
|
|
|
otel
module
|
|
|
uber-fx
module
|
|
|
pkg
|
|
|
httpbarafx
module
|
|
|
httpbaratelemetry
module
|
|
|
httpbarazap
module
|