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

> Learn to register custom HTTP routes in Gorig using httpx.RegisterRouter. Attach Gin routes before server start via an init function for efficient routing.

- Repository: [Jom/gorig](https://github.com/jom-io/gorig)
- Tags: how-to-guide
- Published: 2026-03-04

---

**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`](https://github.com/jom-io/gorig/blob/main/httpx/serv.go), the package creates a global Gin engine (`gEngine`) during initialization and attaches several default middlewares:

```go
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`](https://github.com/jom-io/gorig/blob/main/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`](https://github.com/jom-io/gorig/blob/main/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:

```go
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.

```go
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.

```go
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`](https://github.com/jom-io/gorig/blob/main/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`](https://github.com/jom-io/gorig/blob/main/httpx/tool.go)**: Provides helper utilities for request parsing and response formatting used within route handlers.
- **[`apix/response/response.go`](https://github.com/jom-io/gorig/blob/main/apix/response/response.go)**: Implements standardized JSON response helpers (`Success`, `Error`) that integrate cleanly with the HTTP layer.
- **[`bootstrap/startup.go`](https://github.com/jom-io/gorig/blob/main/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`](https://github.com/jom-io/gorig/blob/main/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`](https://github.com/jom-io/gorig/blob/main/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:

```go
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`](https://github.com/jom-io/gorig/blob/main/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.