Skip to Content
HTTPRoutingAuto-generated Router

Automatic Router Generation

Overview

The goframe HTTP generator provides automatic router generation by scanning your handler methods for special documentation comments and generating the corresponding route registration code. This eliminates the need to manually maintain route definitions.

How It Works

The system works in three main steps:

  1. Package Discovery: Automatically discovers root handler packages (containing router.go and registry.go) and their subfolders
  2. Annotation Scanning: Scans Go files for methods with goframe:http_route comments across all handler packages
  3. Code Generation: Generates router registration code using http.ServeMux.HandleFunc

Handler Structure

Define your handlers using the standard http.HandlerFunc pattern:

type UserHandler struct { userService *UserService } func (h *UserHandler) CreateUser() http.HandlerFunc { return httpx.Wrap(func(r *http.Request) (httpx.Response, error) { // Your business logic here return httpx.JSON.Created(nil), nil }) }

Route Annotation Syntax

Use the goframe:http_route comment above your handler methods to define routes:

Basic Route Definition

// goframe:http_route path=/users method=GET func (h *UserHandler) GetUsers() http.HandlerFunc { return httpx.Wrap(func(r *http.Request) (httpx.Response, error) { // Implementation }) }

Syntax

// goframe:http_route path=/path method=METHOD // goframe:http_route path=/path method=[GET,POST]

Parameters:

  • path - The URL path for the route (required)
  • method - HTTP method(s). Single: GET or multiple: [GET,POST] (default: GET)

Examples

Simple GET Route

// goframe:http_route path=/users method=GET func (h *UserHandler) GetUsers() http.HandlerFunc { return httpx.Wrap(func(r *http.Request) (httpx.Response, error) { // Implementation return httpx.JSON.OK(users), nil }) }

POST Route

// goframe:http_route path=/users method=POST func (h *UserHandler) CreateUser() http.HandlerFunc { return httpx.Wrap(func(r *http.Request) (httpx.Response, error) { // Implementation return httpx.JSON.Created(user), nil }) }

Multiple Methods

// goframe:http_route path=/items method=[GET,POST] func (h *UserHandler) ManageItems() http.HandlerFunc { return httpx.Wrap(func(r *http.Request) (httpx.Response, error) { // Handle both GET and POST }) }

Path Parameters

// goframe:http_route path=/users/{id} method=GET func (h *UserHandler) GetUser() http.HandlerFunc { return httpx.Wrap(func(r *http.Request) (httpx.Response, error) { // Implementation }) }

Generating the Router

Manual Generation

# Generate routes for all discovered handler packages bin/goframe g router # Generate routes for specific packages bin/goframe g router [packages...]

The generator automatically discovers all root handler packages and their subfolders. A root package is identified by the presence of both router.go and registry.go files.

Generated Router Code

The system generates router registration code like:

func Router(p RouterParams) { p.Mux.HandleFunc("GET /users", p.UserHandler.GetUsers()) p.Mux.HandleFunc("POST /users", p.UserHandler.CreateUser()) p.Mux.HandleFunc("GET /users/{id}", p.UserHandler.GetUser()) p.Mux.HandleFunc("GET /items", p.UserHandler.ManageItems()) p.Mux.HandleFunc("POST /items", p.UserHandler.ManageItems()) }

For handlers in subpackages, the generator automatically adds the appropriate import and uses the qualified name:

func Router(p RouterParams) { p.Mux.HandleFunc("GET /users", p.UserHandler.GetUsers()) p.Mux.HandleFunc("GET /dashboard/stats", p.DashboardHandler.GetStats()) }

Hierarchical Package Structure

The generator supports a hierarchical package structure with root packages and subfolders:

Root Handler Packages

A root handler package contains both router.go and registry.go files and serves as the entry point for route registration.

Example Structure

internal/ ├── v1handler/ # Root handler package │ ├── router.go # Generated router with route registrations │ ├── registry.go # Generated handler registry │ ├── handler_user.go # Root level handlers │ ├── handler_order.go │ ├── profile/ # Subfolder with handlers │ │ └── handler_profile.go │ └── admin/ # Subfolder with handlers │ ├── handler_admin.go │ └── reports/ # Nested subfolder │ └── handler_reports.go └── v2handler/ # Another root handler package ├── router.go # Separate router for v2 ├── registry.go # Separate registry for v2 └── handler_user.go

Package Discovery Rules

  • Root packages: Must contain both router.go and registry.go
  • Subfolders: Contain only handler files, no router.go or registry.go
  • Auto-discovery: The generator automatically finds all root packages and their subfolders
  • Import handling: Handlers from subfolders are automatically imported into the root package’s router

Complete Example

// handler_user.go package v1handler import ( "net/http" "github.com/alexisvisco/goframe/http/httpx" ) type UserHandler struct { userService *UserService } // goframe:http_route path=/users method=GET func (h *UserHandler) GetUsers() http.HandlerFunc { return httpx.Wrap(func(r *http.Request) (httpx.Response, error) { users, err := h.userService.GetAllUsers() if err != nil { return nil, err } return httpx.JSON.OK(users), nil }) } // goframe:http_route path=/users method=POST func (h *UserHandler) CreateUser() http.HandlerFunc { return httpx.Wrap(func(r *http.Request) (httpx.Response, error) { // Parse request, create user user, err := h.userService.CreateUser(name, email) if err != nil { return httpx.JSON.BadRequest(err), nil } return httpx.JSON.Created(user), nil }) } // goframe:http_route path=/users/{id} method=GET func (h *UserHandler) GetUser() http.HandlerFunc { return httpx.Wrap(func(r *http.Request) (httpx.Response, error) { id := r.PathValue("id") user, err := h.userService.GetUser(id) if err != nil { return httpx.JSON.NotFound(err), nil } return httpx.JSON.OK(user), nil }) }

After running the generator, this creates a router with:

func Router(p RouterParams) { p.Mux.HandleFunc("GET /users", p.UserHandler.GetUsers()) p.Mux.HandleFunc("POST /users", p.UserHandler.CreateUser()) p.Mux.HandleFunc("GET /users/{id}", p.UserHandler.GetUser()) }

Multi-Package Example

internal/ ├── v1handler/ # Root package │ ├── router.go │ ├── registry.go │ ├── handler_user.go │ └── dashboard/ # Subfolder │ └── handler_stats.go └── adminhandler/ # Another root package ├── router.go ├── registry.go └── handler_admin.go

This structure generates separate routers for each root package:

v1handler/router.go:

func Router(p RouterParams) { p.Mux.HandleFunc("GET /users", p.UserHandler.GetUsers()) p.Mux.HandleFunc("GET /dashboard/stats", p.StatsHandler.GetStats()) }

adminhandler/router.go:

func Router(p RouterParams) { p.Mux.HandleFunc("GET /admin/users", p.AdminHandler.GetUsers()) }

Benefits

  • Organized codebase: Separate concerns into logical packages
  • Automatic discovery: No manual package configuration required
  • Scalable architecture: Support for complex hierarchical structures
  • Multiple API versions: Each root package can represent different API versions
  • Clean imports: Automatic import management for subpackage handlers
Last updated on