diff --git a/amaro.go b/amaro.go index b0cca60..cb3f665 100644 --- a/amaro.go +++ b/amaro.go @@ -106,7 +106,7 @@ type AppOption func(*App) // New creates a new instance of the Amaro App with optional configuration. func New(options ...AppOption) *App { app := &App{ - middlewares: make([]Middleware, 0), + middlewares: []Middleware{Recovery()}, // Add Recovery middleware by default pool: &sync.Pool{ New: func() interface{} { // We can't fully init here because we need w/r, but we create the struct diff --git a/middlewares/suite_test.go b/middlewares/suite_test.go index 3b50c79..cf518f0 100644 --- a/middlewares/suite_test.go +++ b/middlewares/suite_test.go @@ -14,7 +14,7 @@ import ( func TestMiddlewares(t *testing.T) { app := amaro.New(amaro.WithRouter(routers.NewTrieRouter())) - app.Use(middlewares.Recovery()) + // app.Use(amaro.Recovery()) // Already added by default in amaro.New() app.Use(middlewares.RequestID()) app.Use(middlewares.Secure()) app.Use(middlewares.CORS()) diff --git a/middlewares/recovery.go b/recovery.go similarity index 73% rename from middlewares/recovery.go rename to recovery.go index 16430ca..db99b10 100644 --- a/middlewares/recovery.go +++ b/recovery.go @@ -1,17 +1,15 @@ -package middlewares +package amaro import ( "fmt" "net/http" "runtime" - - "github.com/buildwithgo/amaro" ) // Recovery recovers from panics, logs the stack trace, and returns an Internal Server Error. -func Recovery() amaro.Middleware { - return func(next amaro.Handler) amaro.Handler { - return func(c *amaro.Context) error { +func Recovery() Middleware { + return func(next Handler) Handler { + return func(c *Context) error { defer func() { if err := recover(); err != nil { stack := make([]byte, 4096) diff --git a/router.go b/router.go index ae76f23..7995b37 100644 --- a/router.go +++ b/router.go @@ -10,6 +10,47 @@ type Route struct { Middlewares []Middleware } +// ParamParser defines a function that checks if a path segment is a parameter. +// It returns true and the parameter name if it is, false otherwise. +type ParamParser func(segment string) (bool, string) + +// WildcardParser defines a function that checks if a path segment is a wildcard. +// It returns true and the wildcard name if it is, false otherwise. +type WildcardParser func(segment string) (bool, string) + +// RouterConfig defines configuration for Router. +type RouterConfig struct { + ParamParser ParamParser + WildcardParser WildcardParser +} + +// DefaultParamParser implements the standard :param and {param} syntax. +func DefaultParamParser(segment string) (bool, string) { + if len(segment) > 0 && segment[0] == ':' { + return true, segment[1:] + } + if len(segment) > 2 && segment[0] == '{' && segment[len(segment)-1] == '}' { + return true, segment[1 : len(segment)-1] + } + return false, "" +} + +// DefaultWildcardParser implements the standard *wildcard syntax. +func DefaultWildcardParser(segment string) (bool, string) { + if len(segment) > 0 && segment[0] == '*' { + return true, segment[1:] + } + return false, "" +} + +// DefaultRouterConfig returns the default configuration. +func DefaultRouterConfig() RouterConfig { + return RouterConfig{ + ParamParser: DefaultParamParser, + WildcardParser: DefaultWildcardParser, + } +} + // Router is the interface that all router implementations must satisfy. // It allows for swappable routing strategies. type Router interface { diff --git a/routers/decoupled_test.go b/routers/decoupled_test.go index c8dc73c..6cc8b0b 100644 --- a/routers/decoupled_test.go +++ b/routers/decoupled_test.go @@ -16,7 +16,7 @@ func TestDecoupledParamSyntax(t *testing.T) { return false, "" } - config := DefaultTrieRouterConfig() + config := amaro.DefaultRouterConfig() config.ParamParser = customParser r := NewTrieRouter(WithConfig(config)) diff --git a/routers/trie.go b/routers/trie.go index c68c49d..9967edb 100644 --- a/routers/trie.go +++ b/routers/trie.go @@ -23,60 +23,19 @@ type node struct { amaro.Route } -// ParamParser defines a function that checks if a path segment is a parameter. -// It returns true and the parameter name if it is, false otherwise. -type ParamParser func(segment string) (bool, string) - -// WildcardParser defines a function that checks if a path segment is a wildcard. -// It returns true and the wildcard name if it is, false otherwise. -type WildcardParser func(segment string) (bool, string) - -// TrieRouterConfig defines configuration for TrieRouter. -type TrieRouterConfig struct { - ParamParser ParamParser - WildcardParser WildcardParser -} - -// DefaultParamParser implements the standard :param and {param} syntax. -func DefaultParamParser(segment string) (bool, string) { - if len(segment) > 0 && segment[0] == ':' { - return true, segment[1:] - } - if len(segment) > 2 && segment[0] == '{' && segment[len(segment)-1] == '}' { - return true, segment[1 : len(segment)-1] - } - return false, "" -} - -// DefaultWildcardParser implements the standard *wildcard syntax. -func DefaultWildcardParser(segment string) (bool, string) { - if len(segment) > 0 && segment[0] == '*' { - return true, segment[1:] - } - return false, "" -} - -// DefaultTrieRouterConfig returns the default configuration. -func DefaultTrieRouterConfig() TrieRouterConfig { - return TrieRouterConfig{ - ParamParser: DefaultParamParser, - WildcardParser: DefaultWildcardParser, - } -} - // TrieRouter is a trie-based router using a map for children. // It supports :param and *wildcard parameters. type TrieRouter struct { root map[string]*node // method -> root node globalMiddlewares []amaro.Middleware - config TrieRouterConfig + config amaro.RouterConfig } // TrieRouterOption configures TrieRouter. type TrieRouterOption func(*TrieRouter) // WithConfig sets the router configuration. -func WithConfig(config TrieRouterConfig) TrieRouterOption { +func WithConfig(config amaro.RouterConfig) TrieRouterOption { return func(r *TrieRouter) { r.config = config } @@ -86,7 +45,7 @@ func WithConfig(config TrieRouterConfig) TrieRouterOption { func NewTrieRouter(opts ...TrieRouterOption) *TrieRouter { r := &TrieRouter{ root: make(map[string]*node), - config: DefaultTrieRouterConfig(), + config: amaro.DefaultRouterConfig(), } for _, opt := range opts { opt(r)