rtr

package module
v0.1.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 17, 2025 License: AGPL-3.0 Imports: 4 Imported by: 0

README

HTTP Router Package

A flexible and feature-rich HTTP router implementation for Go applications that supports route grouping, middleware chains, and nested routing structures.

Tests Status Go Report Card PkgGoDev License

Features

  • Route Management: Define and manage HTTP routes with support for all standard HTTP methods using exact path matching
  • Route Groups: Group related routes with shared prefixes and middleware
  • Middleware Support:
    • Pre-route (before) middleware
    • Post-route (after) middleware
    • Support at router, group, and individual route levels
    • Built-in panic recovery middleware
  • Nested Groups: Create hierarchical route structures with nested groups
  • Flexible API: Chainable methods for intuitive route and group configuration
  • Standard Interface: Implements http.Handler interface for seamless integration

Middleware

Built-in Middleware
Recovery Middleware

The router includes a built-in recovery middleware that catches panics in your handlers and returns a 500 Internal Server Error response instead of crashing the server. This middleware is added by default when you create a new router with NewRouter().

// This is automatically added when you create a new router
router := router.NewRouter()

// But you can also add it manually if needed
router.AddBeforeMiddlewares([]router.Middleware{router.RecoveryMiddleware})
Custom Middleware

You can create your own middleware by implementing the Middleware type:

func myMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // Do something before the handler runs
        log.Println("Before handler")
        
        // Call the next handler
        next.ServeHTTP(w, r)
        
        // Do something after the handler runs
        log.Println("After handler")
    })
}

// Add it to your router
router.AddBeforeMiddlewares([]router.Middleware{myMiddleware})

Core Components

Router

The main router component that handles HTTP requests and manages routes and groups.

router := router.NewRouter()
Routes

Individual route definitions that specify HTTP method, path, and handler.

// Using shortcut methods
route := router.Get("/users", handleUsers)      // Exact match: /users
route := router.Post("/users", createUser)     // Exact match: /users
route := router.Put("/users/123", updateUser)  // Exact match required: /users/123
route := router.Delete("/users/123", deleteUser) // Exact match required: /users/123

// Using method chaining
route := router.NewRoute()
    .SetMethod("GET")
    .SetPath("/users")
    .SetHandler(handleUsers)
Groups

Route groups that share common prefixes and middleware.

group := router.NewGroup()
    .SetPrefix("/api")
    .AddRoute(route)

Usage Examples

Basic Router Setup
r := router.NewRouter()

// Add routes using shortcut methods
r.AddRoute(router.Get("/hello", func(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, World!")
}))

// Add routes using method chaining
r.AddRoute(router.NewRoute()
    .SetMethod("GET")
    .SetPath("/users")
    .SetHandler(handleUsers))
Using Route Groups
// Create an API group
apiGroup := router.NewGroup().SetPrefix("/api")

// Add routes to the group
apiGroup.AddRoute(router.NewRoute()
    .SetMethod("GET")
    .SetPath("/users")
    .SetHandler(handleUsers))

// Add the group to the router
r.AddGroup(apiGroup)
Adding Middleware
// Router-level middleware
r.AddBeforeMiddlewares([]router.Middleware{
    loggingMiddleware,
    authenticationMiddleware,
})

// Group-level middleware
apiGroup.AddBeforeMiddlewares([]router.Middleware{
    apiKeyMiddleware,
})

// Route-level middleware
route.AddBeforeMiddlewares([]router.Middleware{
    specificRouteMiddleware,
})

Path Matching

This router uses exact path matching:

  • Paths must match exactly as defined
  • No built-in path parameters (e.g., /users/:id)
  • No automatic trailing slash redirection

Domain-based Routing

The router supports domain-based routing, allowing you to define routes that only match specific domain names or patterns.

Creating a Domain
// Create a domain with exact match
domain := router.NewDomain("example.com")

// Create a domain with wildcard subdomain matching
wildcardDomain := router.NewDomain("*.example.com")

// Create a domain that matches multiple patterns
multiDomain := router.NewDomain("example.com", "api.example.com", "*.example.org")
Adding Routes to a Domain
// Create a new domain
domain := router.NewDomain("api.example.com")

// Add routes directly to the domain
domain.AddRoute(router.Get("/users", handleUsers))

// Add multiple routes at once
domain.AddRoutes([]router.RouteInterface{
    router.Get("/users", handleUsers),
    router.Post("/users", createUser),
})
Adding Groups to a Domain
// Create a domain
domain := router.NewDomain("api.example.com")

// Create an API group
apiGroup := router.NewGroup().SetPrefix("/v1")

// Add routes to the group
apiGroup.AddRoute(router.Get("/products", handleProducts))

// Add the group to the domain
domain.AddGroup(apiGroup)

// Add the domain to the router
router.AddDomain(domain)
Domain Matching

Domains are matched against the Host header of incoming requests. The matching supports:

Basic Domain Matching
  • Exact matches (example.com)
  • Wildcard subdomains (*.example.com)
  • Multiple patterns per domain
Port Matching
  • No port in pattern: Matches any port on that host

    domain := router.NewDomain("example.com")  // Matches example.com, example.com:8080, example.com:3000, etc.
    
  • Exact port: Requires exact port match

    domain := router.NewDomain("example.com:8080")  // Only matches example.com:8080
    
  • Wildcard port: Matches any port on that host

    domain := router.NewDomain("example.com:*")  // Matches example.com with any port
    
  • IPv4 and IPv6 support:

    // IPv4 with port
    ipv4Domain := router.NewDomain("127.0.0.1:8080")  // Matches 127.0.0.1:8080
    
    // IPv6 with port (note the square brackets)
    ipv6Domain := router.NewDomain("[::1]:8080")  // Matches [::1]:8080
    
Examples
// Match any port on example.com
anyPort := router.NewDomain("example.com")

// Match only port 8080
exactPort := router.NewDomain("example.com:8080")

// Match any subdomain on any port
wildcardSubdomain := router.NewDomain("*.example.com:*")

// Match localhost on any port
localhost := router.NewDomain("localhost:*")

// Match IPv6 localhost on port 3000
ipv6Localhost := router.NewDomain("[::1]:3000")
Middleware on Domains

Middleware can be added at the domain level to apply to all routes within that domain:

domain := router.NewDomain("admin.example.com")

// Add middleware that will run before all routes in this domain
domain.AddBeforeMiddlewares([]router.Middleware{
    adminAuthMiddleware,
    loggingMiddleware,
})

// Add middleware that will run after all routes in this domain
domain.AddAfterMiddlewares([]router.Middleware{
    responseTimeMiddleware,
})

Interfaces

RouterInterface

The main router interface that provides methods for managing routes and groups:

  • GetPrefix() / SetPrefix(): Manage router prefix
  • AddGroup() / AddGroups(): Add route groups
  • AddRoute() / AddRoutes(): Add individual routes
  • AddBeforeMiddlewares() / AddAfterMiddlewares(): Add middleware chains
  • ServeHTTP(): Handle HTTP requests
GroupInterface

Interface for managing route groups:

  • GetPrefix() / SetPrefix(): Manage group prefix
  • AddRoute() / AddRoutes(): Add routes to the group
  • AddGroup() / AddGroups(): Add nested groups
  • AddBeforeMiddlewares() / AddAfterMiddlewares(): Add group-level middleware
RouteInterface

Interface for configuring individual routes:

  • GetMethod() / SetMethod(): HTTP method configuration
  • GetPath() / SetPath(): URL path configuration
  • GetHandler() / SetHandler(): Route handler configuration
  • GetName() / SetName(): Route naming
  • AddBeforeMiddlewares() / AddAfterMiddlewares(): Route-specific middleware
Shortcut Methods

The package provides shortcut methods for common HTTP methods:

  • Get(path string, handler Handler) RouteInterface - Creates a GET route
  • Post(path string, handler Handler) RouteInterface - Creates a POST route
  • Put(path string, handler Handler) RouteInterface - Creates a PUT route
  • Delete(path string, handler Handler) RouteInterface - Creates a DELETE route

These methods automatically set the HTTP method, path, and handler, making route creation more concise.

Testing

The package includes comprehensive test coverage:

  • router_test.go: Core router functionality tests
  • router_integration_test.go: Integration tests
  • route_test.go: Route-specific tests
  • group_test.go: Group functionality tests
  • examples/basic/: Complete example with tests

Run tests using:

# From the root directory
go test .

# Or to run all tests including examples
go test ./...

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func RecoveryMiddleware

func RecoveryMiddleware(next http.Handler) http.Handler

RecoveryMiddleware creates a new middleware that recovers from panics. It logs the panic details and returns a 500 Internal Server Error response. This should typically be added as one of the first middlewares in the chain.

Types

type DomainInterface

type DomainInterface interface {
	// GetPatterns returns the domain patterns that this domain matches against
	GetPatterns() []string

	// SetPatterns sets the domain patterns for this domain and returns the domain for method chaining
	SetPatterns(patterns ...string) DomainInterface

	// AddRoute adds a route to this domain and returns the domain for method chaining
	AddRoute(route RouteInterface) DomainInterface

	// AddRoutes adds multiple routes to this domain and returns the domain for method chaining
	AddRoutes(routes []RouteInterface) DomainInterface

	// GetRoutes returns all routes that belong to this domain
	GetRoutes() []RouteInterface

	// AddGroup adds a group to this domain and returns the domain for method chaining
	AddGroup(group GroupInterface) DomainInterface

	// AddGroups adds multiple groups to this domain and returns the domain for method chaining
	AddGroups(groups []GroupInterface) DomainInterface

	// GetGroups returns all groups that belong to this domain
	GetGroups() []GroupInterface

	// AddBeforeMiddlewares adds middleware functions to be executed before any route handler in this domain
	// Returns the domain for method chaining
	AddBeforeMiddlewares(middleware []Middleware) DomainInterface

	// GetBeforeMiddlewares returns all middleware functions that will be executed before any route handler in this domain
	GetBeforeMiddlewares() []Middleware

	// AddAfterMiddlewares adds middleware functions to be executed after any route handler in this domain
	// Returns the domain for method chaining
	AddAfterMiddlewares(middleware []Middleware) DomainInterface

	// GetAfterMiddlewares returns all middleware functions that will be executed after any route handler in this domain
	GetAfterMiddlewares() []Middleware

	// Match checks if the given host matches any of this domain's patterns
	Match(host string) bool
}

DomainInterface defines the interface for a domain that can have routes and groups. A domain represents a collection of routes and groups that are only accessible when the request's Host header matches the domain's patterns.

func NewDomain

func NewDomain(patterns ...string) DomainInterface

NewDomain creates a new domain with the given patterns

type GroupInterface

type GroupInterface interface {
	// GetPrefix returns the URL path prefix associated with this group.
	GetPrefix() string
	// SetPrefix sets the URL path prefix for this group and returns the group for method chaining.
	SetPrefix(prefix string) GroupInterface

	// AddRoute adds a single route to this group and returns the group for method chaining.
	AddRoute(route RouteInterface) GroupInterface
	// AddRoutes adds multiple routes to this group and returns the group for method chaining.
	AddRoutes(routes []RouteInterface) GroupInterface
	// GetRoutes returns all routes that belong to this group.
	GetRoutes() []RouteInterface

	// AddGroup adds a single nested group to this group and returns the group for method chaining.
	AddGroup(group GroupInterface) GroupInterface
	// AddGroups adds multiple nested groups to this group and returns the group for method chaining.
	AddGroups(groups []GroupInterface) GroupInterface
	// GetGroups returns all nested groups that belong to this group.
	GetGroups() []GroupInterface

	// AddBeforeMiddlewares adds middleware functions to be executed before any route handler in this group.
	// Returns the group for method chaining.
	AddBeforeMiddlewares(middleware []Middleware) GroupInterface
	// GetBeforeMiddlewares returns all middleware functions that will be executed before any route handler in this group.
	GetBeforeMiddlewares() []Middleware

	// AddAfterMiddlewares adds middleware functions to be executed after any route handler in this group.
	// Returns the group for method chaining.
	AddAfterMiddlewares(middleware []Middleware) GroupInterface
	// GetAfterMiddlewares returns all middleware functions that will be executed after any route handler in this group.
	GetAfterMiddlewares() []Middleware
}

GroupInterface defines the interface for a group of routes. A group represents a collection of routes that share common properties such as a URL prefix and middleware. Groups can also be nested to create hierarchical route structures.

func NewGroup

func NewGroup() GroupInterface

NewGroup creates and returns a new GroupInterface implementation. This is used to create a new route group that can be added to a router.

type Handler

type Handler func(http.ResponseWriter, *http.Request)

Handler represents the function that handles a request. It is a function type that takes an http.ResponseWriter and an *http.Request as parameters. This is the standard Go HTTP handler function signature.

type Middleware

type Middleware func(http.Handler) http.Handler

Middleware represents a middleware function. It is a function type that takes an http.Handler and returns an http.Handler. Middleware functions can be used to process requests before or after they reach the main handler.

func DefaultMiddlewares

func DefaultMiddlewares() []Middleware

DefaultMiddlewares returns a slice of default middlewares that should be used with the router. Currently, it only includes the RecoveryMiddleware.

type RouteInterface

type RouteInterface interface {
	// GetMethod returns the HTTP method associated with this route.
	GetMethod() string
	// SetMethod sets the HTTP method for this route and returns the route for method chaining.
	SetMethod(method string) RouteInterface

	// GetPath returns the URL path pattern associated with this route.
	GetPath() string
	// SetPath sets the URL path pattern for this route and returns the route for method chaining.
	SetPath(path string) RouteInterface

	// GetHandler returns the handler function associated with this route.
	GetHandler() Handler
	// SetHandler sets the handler function for this route and returns the route for method chaining.
	SetHandler(handler Handler) RouteInterface

	// GetName returns the name identifier associated with this route.
	GetName() string
	// SetName sets the name identifier for this route and returns the route for method chaining.
	SetName(name string) RouteInterface

	// AddBeforeMiddlewares adds middleware functions to be executed before the route handler.
	// Returns the route for method chaining.
	AddBeforeMiddlewares(middleware []Middleware) RouteInterface
	// GetBeforeMiddlewares returns all middleware functions that will be executed before the route handler.
	GetBeforeMiddlewares() []Middleware

	// AddAfterMiddlewares adds middleware functions to be executed after the route handler.
	// Returns the route for method chaining.
	AddAfterMiddlewares(middleware []Middleware) RouteInterface
	// GetAfterMiddlewares returns all middleware functions that will be executed after the route handler.
	GetAfterMiddlewares() []Middleware
}

RouteInterface defines the interface for a single route definition. A route represents a mapping between an HTTP method, a URL path pattern, and a handler function. Routes can also have associated middleware that will be executed before or after the handler.

func Delete

func Delete(path string, handler Handler) RouteInterface

Delete creates a new DELETE route with the given path and handler It is a shortcut method that combines setting the method to DELETE, path, and handler.

func Get

func Get(path string, handler Handler) RouteInterface

Get creates a new GET route with the given path and handler It is a shortcut method that combines setting the method to GET, path, and handler.

func NewRoute

func NewRoute() RouteInterface

This is used to create a new route that can be added to a router or group.

func Post

func Post(path string, handler Handler) RouteInterface

Post creates a new POST route with the given path and handler It is a shortcut method that combines setting the method to POST, path, and handler.

func Put

func Put(path string, handler Handler) RouteInterface

Put creates a new PUT route with the given path and handler It is a shortcut method that combines setting the method to PUT, path, and handler.

type RouterInterface

type RouterInterface interface {
	// GetPrefix returns the URL path prefix associated with this router.
	GetPrefix() string
	// SetPrefix sets the URL path prefix for this router and returns the router for method chaining.
	// The prefix will be prepended to all routes in this router.
	SetPrefix(prefix string) RouterInterface

	// AddGroup adds a single group to this router and returns the router for method chaining.
	// The group's prefix will be combined with the router's prefix for all routes in the group.
	AddGroup(group GroupInterface) RouterInterface
	// AddGroups adds multiple groups to this router and returns the router for method chaining.
	// Each group's prefix will be combined with the router's prefix for all routes in the group.
	AddGroups(groups []GroupInterface) RouterInterface
	// GetGroups returns all groups that belong to this router.
	// Returns a slice of GroupInterface implementations.
	GetGroups() []GroupInterface

	// AddRoute adds a single route to this router and returns the router for method chaining.
	// The route's path will be prefixed with the router's prefix.
	AddRoute(route RouteInterface) RouterInterface
	// AddRoutes adds multiple routes to this router and returns the router for method chaining.
	// Each route's path will be prefixed with the router's prefix.
	AddRoutes(routes []RouteInterface) RouterInterface
	// GetRoutes returns all routes that belong to this router.
	// Returns a slice of RouteInterface implementations.
	GetRoutes() []RouteInterface

	// AddBeforeMiddlewares adds middleware functions to be executed before any route handler.
	// The middleware functions will be executed in the order they are added.
	// Returns the router for method chaining.
	AddBeforeMiddlewares(middleware []Middleware) RouterInterface
	// GetBeforeMiddlewares returns all middleware functions that will be executed before any route handler.
	// Returns a slice of Middleware functions.
	GetBeforeMiddlewares() []Middleware

	// AddAfterMiddlewares adds middleware functions to be executed after any route handler.
	// The middleware functions will be executed in reverse order of how they were added.
	// Returns the router for method chaining.
	AddAfterMiddlewares(middleware []Middleware) RouterInterface
	// GetAfterMiddlewares returns all middleware functions that will be executed after any route handler.
	// Returns a slice of Middleware functions.
	GetAfterMiddlewares() []Middleware

	// AddDomain adds a domain to this router and returns the router for method chaining
	AddDomain(domain DomainInterface) RouterInterface

	// AddDomains adds multiple domains to this router and returns the router for method chaining
	AddDomains(domains []DomainInterface) RouterInterface

	// GetDomains returns all domains that belong to this router
	GetDomains() []DomainInterface

	// ServeHTTP implements the http.Handler interface.
	// It matches the incoming request to the appropriate route and executes the handler.
	ServeHTTP(w http.ResponseWriter, r *http.Request)
}

RouterInterface defines the interface for a router that can handle HTTP requests. A router is responsible for matching incoming HTTP requests to the appropriate route handler and executing any associated middleware.

func NewRouter

func NewRouter() RouterInterface

NewRouter creates and returns a new RouterInterface implementation. This is the main entry point for creating a new router. By default, it includes recovery middleware to handle panics.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL