How to Register Custom HTTP Routes in Gorig Using httpx.RegisterRouter

Call httpx.RegisterRouter from an init() function to attach custom Gin routes to Gorig's global HTTP engine before the server starts.

Gorig provides a thin but powerful wrapper around Gin via the httpx package, allowing developers to register custom HTTP routes while inheriting a pre-configured middleware stack. This article explains how to use httpx.RegisterRouter and httpx.RegisterRouterMid to wire your endpoints into the framework's lifecycle.

Understanding Gorig's HTTP Architecture

Before registering routes, it helps to understand how Gorig initializes its HTTP layer. Inside httpx/serv.go, the package creates a global Gin engine (gEngine) during initialization and attaches several default middlewares:

var gEngine = gin.New()

func init() {
    gEngine.Use(Recovery())
    gEngine.Use(Logger())
    gEngine.Use(CORS())
    gEngine.Use(gzip.Gzip(gzip.BestSpeed))
    gEngine.Use(Debounce(200 * time.Millisecond))
}

This global engine is the foundation onto which all custom routes are mounted. The httpx package exposes two registration helpers—RegisterRouter and RegisterRouterMid—defined at lines 58–68 of httpx/serv.go. Both are designed to be invoked during the init() phase of your application packages, ensuring routes are configured before httpx.Startup (called from bootstrap/startup.go) binds the engine to an http.Server.

Registering Routes with httpx.RegisterRouter

The simplest way to expose endpoints is through httpx.RegisterRouter. This function accepts a closure that receives a pointer to the root gin.RouterGroup, allowing you to define routes using standard Gin syntax.

Basic Route Registration

To register a plain route without additional middleware, call httpx.RegisterRouter inside an init() function:

package myapp

import (
    "github.com/gin-gonic/gin"
    "github.com/jom-io/gorig/apix/response"
    "github.com/jom-io/gorig/global/consts"
    "github.com/jom-io/gorig/httpx"
)

func init() {
    httpx.RegisterRouter(func(r *gin.RouterGroup) {
        r.GET("/hello", func(c *gin.Context) {
            response.Success(c, consts.CurdStatusOkMsg, "Hello, Gorig!")
        })
    })
}

When the application starts, the /hello endpoint will be available on the server, automatically inheriting the default middleware stack (recovery, logging, CORS, etc.).

Route Groups with Middleware via httpx.RegisterRouterMid

For endpoints that require specific middleware—such as authentication or rate limiting—use httpx.RegisterRouterMid. This helper creates a sub-group with the provided middlewares before invoking your registration closure.

package myapi

import (
    "github.com/gin-gonic/gin"
    "github.com/jom-io/gorig/apix/response"
    "github.com/jom-io/gorig/httpx"
    "myproject/mid/auth"
)

func init() {
    // Create an "/api" group protected by auth.Authenticate
    apiGroup := httpx.RegisterRouterMid(
        func(r *gin.RouterGroup, mids ...gin.HandlerFunc) *gin.RouterGroup {
            return r.Group("/api", mids...)
        },
        auth.Authenticate,
    )

    // Register routes on the protected group
    apiGroup.GET("/status", func(c *gin.Context) {
        response.Success(c, "ok", "API is healthy")
    })
    apiGroup.POST("/items", func(c *gin.Context) {
        // Handle creation logic
        response.Success(c, "created", nil)
    })
}

All routes under /api/* will now execute auth.Authenticate before reaching the handler, while routes registered via plain RegisterRouter remain unprotected.

Complete Working Examples

You can combine both registration strategies within the same application. The order of registration does not affect the final routing table, as all routes are accumulated in the global engine before httpx.Startup is invoked.

func init() {
    // Public health check
    httpx.RegisterRouter(func(r *gin.RouterGroup) {
        r.GET("/ping", func(c *gin.Context) {
            response.Success(c, "pong", nil)
        })
    })

    // Protected admin routes
    admin := httpx.RegisterRouterMid(
        func(r *gin.RouterGroup, mids ...gin.HandlerFunc) *gin.RouterGroup {
            return r.Group("/admin", mids...)
        },
        auth.RequireAdmin,
    )
    admin.GET("/dashboard", adminDashboardHandler)
    admin.POST("/config", updateConfigHandler)
}

Key Source Files and Implementation Details

Understanding the underlying source helps debug routing issues and extend functionality:

  • httpx/serv.go (lines 58–68): Contains the RegisterRouter and RegisterRouterMid implementations. The global gEngine is defined here and initialized with default middleware.
  • httpx/tool.go: Provides helper utilities for request parsing and response formatting used within route handlers.
  • apix/response/response.go: Implements standardized JSON response helpers (Success, Error) that integrate cleanly with the HTTP layer.
  • bootstrap/startup.go: Orchestrates the application lifecycle, calling httpx.Startup to bind the configured engine to a running server.

Summary

  • Gorig centralizes HTTP handling in the httpx package, which initializes a global Gin engine with recovery, logging, CORS, and compression middleware.
  • Use httpx.RegisterRouter in an init() function to add simple routes to the root router group.
  • Use httpx.RegisterRouterMid when you need to attach specific middleware to a route group before registering handlers.
  • All routes must be registered before httpx.Startup is invoked (typically from bootstrap/startup.go), after which the server begins listening.

Frequently Asked Questions

When should I use RegisterRouter versus RegisterRouterMid?

Use httpx.RegisterRouter for public endpoints that only need the global default middleware (recovery, logging, CORS, etc.). Use httpx.RegisterRouterMid when you need to apply additional middleware—such as authentication, rate limiting, or request validation—to a specific subset of routes. The latter creates a new Gin router group with the provided middleware chain.

Can I call RegisterRouter from main() instead of init()?

Yes, but it is not recommended. While calling from main() works technically, registering routes in init() ensures they are defined immediately after the httpx package initializes its global engine. This guarantees that all routes are ready before bootstrap/startup.go triggers httpx.Startup, preventing race conditions or missing endpoints during server startup.

How do I add custom middleware to a single route rather than a group?

Gorig's httpx package is optimized for group-level middleware via RegisterRouterMid. For single-route middleware, define the route inside a RegisterRouter closure and chain the middleware directly in the Gin handler definition:

httpx.RegisterRouter(func(r *gin.RouterGroup) {
    r.GET("/special", auth.CheckToken, myHandler)
})

This attaches auth.CheckToken only to the /special endpoint while keeping the route within the global registration pattern.

Where is the global Gin engine configured in the source code?

The global engine (gEngine) is instantiated and configured in httpx/serv.go at the package level. During init(), the engine is wrapped with recovery, logging, CORS, gzip compression, and debounce middleware before any application routes are registered.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →