chimux

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Apr 26, 2025 License: MIT Imports: 9 Imported by: 1

README

chimux Module

A module for the Modular framework.

Overview

The chimux module provides a powerful HTTP router and middleware system for Modular applications by integrating the popular go-chi router. This module allows Modular applications to easily set up and configure HTTP routing with middleware support, all while maintaining the modular architecture and configuration management that Modular offers.

Features

  • Full integration of go-chi router within the Modular framework
  • Configurable middleware stack with pre-defined middleware options
  • Easy route registration through service interfaces
  • Support for RESTful resource patterns
  • Mount handlers at specific path prefixes
  • Configurable CORS settings
  • Timeout management for request handling
  • Base path configuration for all routes

Installation

go get github.com/GoCodeAlone/modular/modules/chimux@v1.0.0

Usage

package main

import (
	"github.com/GoCodeAlone/modular"
	"github.com/GoCodeAlone/modular/modules/chimux"
	"log/slog"
	"net/http"
	"os"
)

func main() {
	// Create a new application
	app := modular.NewStdApplication(
		modular.NewStdConfigProvider(&AppConfig{}),
		slog.New(slog.NewTextHandler(os.Stdout, nil)),
	)

	// Register the chimux module
	app.RegisterModule(chimux.NewChimuxModule())
	
	// Register your API module that will use the router
	app.RegisterModule(NewAPIModule())

	// Run the application
	if err := app.Run(); err != nil {
		app.Logger().Error("Application error", "error", err)
		os.Exit(1)
	}
}

// APIModule that uses the chimux router
type APIModule struct {
	router chimux.RouterService
}

func NewAPIModule() modular.Module {
	return &APIModule{}
}

func (m *APIModule) Name() string {
	return "api"
}

func (m *APIModule) Dependencies() []string {
	return []string{"chimux"} // Depend on chimux module
}

func (m *APIModule) RequiresServices() []modular.ServiceDependency {
	return []modular.ServiceDependency{
		{
			Name:     "chimux.router",
			Required: true,
		},
	}
}

func (m *APIModule) Init(app modular.Application) error {
	// Get the router service
	if err := app.GetService("chimux.router", &m.router); err != nil {
		return err
	}
	
	// Register routes
	m.router.Get("/api/health", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte(`{"status":"ok"}`))
	})
	
	m.router.Route("/api/users", func(r chimux.Router) {
		r.Get("/", m.listUsers)
		r.Post("/", m.createUser)
		r.Route("/{id}", func(r chimux.Router) {
			r.Get("/", m.getUser)
			r.Put("/", m.updateUser)
			r.Delete("/", m.deleteUser)
		})
	})
	
	return nil
}

// Other required module methods...

Configuration

The chimux module supports the following configuration options:

Option Type Required Default Description
AllowedOrigins []string No ["*"] List of allowed origins for CORS requests.
AllowedMethods []string No ["GET","POST","PUT","DELETE","OPTIONS"] List of allowed HTTP methods.
AllowedHeaders []string No ["Origin","Accept","Content-Type","X-Requested-With","Authorization"] List of allowed request headers.
AllowCredentials bool No false Allow credentials in CORS requests.
MaxAge int No 300 Maximum age for CORS preflight cache in seconds.
Timeout int No 60000 Default request timeout in milliseconds.
BasePath string No - A base path prefix for all routes registered through this module.
EnabledMiddleware []string No ["Heartbeat","RequestID","RealIP","Logger","Recoverer"] List of middleware to enable by default.
Example Configuration
# config.yaml
chimux:
  allowedorigins: ["*"]
  allowedmethods: ["GET","POST","PUT","DELETE","OPTIONS"]
  allowedheaders: ["Origin","Accept","Content-Type","X-Requested-With","Authorization"]
  allowcredentials: false
  maxage: 300
  timeout: 60000
  basepath: "/api"
  enabledmiddleware: ["Heartbeat", "RequestID", "RealIP", "Logger", "Recoverer"]

Middleware Configuration

chimux supports two approaches for configuring middleware:

1. Configuration-based middleware

Define which built-in middleware to enable through configuration:

chimux:
  enabledmiddleware: 
    - "RequestID"
    - "RealIP"
    - "Logger"
    - "Recoverer"
    - "StripSlashes"
    - "Timeout"
2. Programmatic middleware registration

For custom middleware, you can register it during module initialization or by implementing the MiddlewareProvider interface:

// Custom middleware provider module
type AuthMiddlewareModule struct {
    // module implementation
}

func (m *AuthMiddlewareModule) ProvidesServices() []modular.ServiceProvider {
    return []modular.ServiceProvider{
        {
            Name: "auth.middleware",
            Instance: chimux.MiddlewareProvider(func() []chimux.Middleware {
                return []chimux.Middleware{
                    m.jwtAuthMiddleware,
                    m.roleCheckerMiddleware,
                }
            }),
        },
    }
}

// Define your custom middleware
func (m *AuthMiddlewareModule) jwtAuthMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // JWT authentication logic
        next.ServeHTTP(w, r)
    })
}

The chimux module will automatically discover and use any registered MiddlewareProvider services using interface-based service matching.

Advanced Usage

Adding custom middleware to specific routes
func (m *APIModule) Init(app modular.Application) error {
    // Get the router service
    err := app.GetService("chimux.router", &m.router)
    if err != nil {
        return err
    }
    
    // Create middleware
    adminOnly := func(next http.Handler) http.Handler {
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            // Check if user is admin
            if isAdmin := checkAdmin(r); !isAdmin {
                http.Error(w, "Unauthorized", http.StatusUnauthorized)
                return
            }
            next.ServeHTTP(w, r)
        })
    }
    
    // Apply middleware to specific routes
    m.router.Route("/admin", func(r chimux.Router) {
        r.Use(adminOnly)
        r.Get("/dashboard", m.adminDashboard)
        r.Post("/users", m.adminCreateUser)
    })
    
    return nil
}
Accessing the underlying chi.Router

If needed, you can access the underlying chi.Router for advanced functionality:

func (m *APIModule) Init(app modular.Application) error {
    var router chimux.ChiRouterService
    if err := app.GetService("chimux.router", &router); err != nil {
        return err
    }
    
    // Access the underlying chi.Router
    chiRouter := router.ChiRouter()
    
    // Use chi-specific features
    chiRouter.Mount("/legacy", legacyHandler)
    
    return nil
}

License

MIT License

Documentation

Index

Constants

View Source
const ModuleName = "chimux"

ModuleName is the name of this module

View Source
const ServiceName = "chimux.router"

ServiceName is the name of the service provided by this module (the chi router)

Variables

This section is empty.

Functions

func NewChiMuxModule

func NewChiMuxModule() modular.Module

NewChiMuxModule creates a new instance of the chimux module

Types

type ChiMuxConfig

type ChiMuxConfig struct {
	AllowedOrigins []string `yaml:"allowed_origins" default:"[\"*\"]" desc:"List of allowed origins for CORS requests."`                              // List of allowed origins for CORS requests.
	AllowedMethods []string `yaml:"allowed_methods" default:"[\"GET\",\"POST\",\"PUT\",\"DELETE\",\"OPTIONS\"]" desc:"List of allowed HTTP methods."` // List of allowed HTTP methods.
	AllowedHeaders []string ``                                                                                                                        // List of allowed request headers.
	/* 152-byte string literal not displayed */
	AllowCredentials bool   `yaml:"allow_credentials" default:"false" desc:"Allow credentials in CORS requests."`      // Allow credentials in CORS requests.
	MaxAge           int    `yaml:"max_age" default:"300" desc:"Maximum age for CORS preflight cache in seconds."`     // Maximum age for CORS preflight cache in seconds.
	Timeout          int    `yaml:"timeout" default:"60000" desc:"Default request timeout."`                           // Default request timeout.
	BasePath         string `yaml:"basepath" desc:"A base path prefix for all routes registered through this module."` // A base path prefix for all routes registered through this module.
}

ChiMuxConfig holds the configuration for the chimux module

func (*ChiMuxConfig) Validate

func (c *ChiMuxConfig) Validate() error

Validate implements the modular.ConfigValidator interface

type ChiMuxModule

type ChiMuxModule struct {
	// contains filtered or unexported fields
}

ChiMuxModule represents the chimux module

func (*ChiMuxModule) ChiRouter

func (m *ChiMuxModule) ChiRouter() chi.Router

ChiRouter returns the underlying chi.Router instance

func (*ChiMuxModule) Constructor

func (m *ChiMuxModule) Constructor() modular.ModuleConstructor

Constructor provides a dependency injection constructor for the module

func (*ChiMuxModule) Delete

func (m *ChiMuxModule) Delete(pattern string, handler http.HandlerFunc)

Delete registers a DELETE handler for the pattern

func (*ChiMuxModule) Dependencies

func (m *ChiMuxModule) Dependencies() []string

Dependencies returns the names of modules this module depends on

func (*ChiMuxModule) Get

func (m *ChiMuxModule) Get(pattern string, handler http.HandlerFunc)

RouterService interface implementation Get registers a GET handler for the pattern

func (*ChiMuxModule) GetTenantConfig

func (m *ChiMuxModule) GetTenantConfig(tenantID modular.TenantID) *ChiMuxConfig

GetTenantConfig retrieves the loaded configuration for a specific tenant Returns the base config if no specific tenant config is found.

func (*ChiMuxModule) Handle

func (m *ChiMuxModule) Handle(pattern string, handler http.Handler)

Handle registers a handler for a specific pattern

func (*ChiMuxModule) HandleFunc

func (m *ChiMuxModule) HandleFunc(pattern string, handler http.HandlerFunc)

HandleFunc registers a handler function for a specific pattern

func (*ChiMuxModule) Head

func (m *ChiMuxModule) Head(pattern string, handler http.HandlerFunc)

Head registers a HEAD handler for the pattern

func (*ChiMuxModule) Init

func (m *ChiMuxModule) Init(app modular.Application) error

Init initializes the module

func (*ChiMuxModule) Mount

func (m *ChiMuxModule) Mount(pattern string, handler http.Handler)

Mount attaches another http.Handler at the given pattern

func (*ChiMuxModule) Name

func (m *ChiMuxModule) Name() string

Name returns the name of the module

func (*ChiMuxModule) OnTenantRegistered

func (m *ChiMuxModule) OnTenantRegistered(tenantID modular.TenantID)

OnTenantRegistered is called when a new tenant is registered

func (*ChiMuxModule) OnTenantRemoved

func (m *ChiMuxModule) OnTenantRemoved(tenantID modular.TenantID)

OnTenantRemoved is called when a tenant is removed

func (*ChiMuxModule) Options

func (m *ChiMuxModule) Options(pattern string, handler http.HandlerFunc)

Options registers an OPTIONS handler for the pattern

func (*ChiMuxModule) Patch

func (m *ChiMuxModule) Patch(pattern string, handler http.HandlerFunc)

Patch registers a PATCH handler for the pattern

func (*ChiMuxModule) Post

func (m *ChiMuxModule) Post(pattern string, handler http.HandlerFunc)

Post registers a POST handler for the pattern

func (*ChiMuxModule) ProvidesServices

func (m *ChiMuxModule) ProvidesServices() []modular.ServiceProvider

ProvidesServices declares services provided by this module

func (*ChiMuxModule) Put

func (m *ChiMuxModule) Put(pattern string, handler http.HandlerFunc)

Put registers a PUT handler for the pattern

func (*ChiMuxModule) RegisterConfig

func (m *ChiMuxModule) RegisterConfig(app modular.Application) error

RegisterConfig registers the module's configuration structure

func (*ChiMuxModule) RequiresServices

func (m *ChiMuxModule) RequiresServices() []modular.ServiceDependency

RequiresServices declares services required by this module

func (*ChiMuxModule) Route

func (m *ChiMuxModule) Route(pattern string, fn func(r Router))

Route creates a new sub-router for the given pattern

func (*ChiMuxModule) ServeHTTP

func (m *ChiMuxModule) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP implements the http.Handler interface to properly handle base path prefixing

func (*ChiMuxModule) Start

func (m *ChiMuxModule) Start(context.Context) error

Start performs startup logic for the module

func (*ChiMuxModule) Stop

func (m *ChiMuxModule) Stop(context.Context) error

Stop performs shutdown logic for the module

func (*ChiMuxModule) Use

func (m *ChiMuxModule) Use(middleware ...func(http.Handler) http.Handler)

Use appends middleware to the chain

type ChiRouterService

type ChiRouterService interface {
	RouterService
	ChiRouter() chi.Router
}

ChiRouterService extends RouterService with methods to access the underlying chi router

type Middleware

type Middleware func(http.Handler) http.Handler

Middleware is an alias for the chi middleware handler function

type MiddlewareProvider

type MiddlewareProvider interface {
	ProvideMiddleware() []Middleware
}

MiddlewareProvider defines a service that provides middleware for the chimux router

type Router

type Router interface {
	RouterService
}

Router is the sub-router interface

type RouterService

type RouterService interface {
	// Standard HTTP method handlers
	Get(pattern string, handler http.HandlerFunc)
	Post(pattern string, handler http.HandlerFunc)
	Put(pattern string, handler http.HandlerFunc)
	Delete(pattern string, handler http.HandlerFunc)
	Patch(pattern string, handler http.HandlerFunc)
	Head(pattern string, handler http.HandlerFunc)
	Options(pattern string, handler http.HandlerFunc)

	// Route creates a new sub-router for the given pattern
	Route(pattern string, fn func(r Router))

	// Mount attaches another http.Handler at the given pattern
	Mount(pattern string, handler http.Handler)

	// Use appends middleware to the chain
	Use(middleware ...func(http.Handler) http.Handler)

	// Handle registers a handler for a specific pattern
	Handle(pattern string, handler http.Handler)

	// HandleFunc registers a handler function for a specific pattern
	HandleFunc(pattern string, handler http.HandlerFunc)
}

RouterService defines the interface for working with the Chi router

Jump to

Keyboard shortcuts

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