Router/README.md
2025-05-07 12:30:52 -05:00

131 lines
3.2 KiB
Markdown

# Router
A high-performance router for Go with support for path parameters, wildcards, middleware, and route grouping. Sports an incredibly simple API over the top of a prefix tree data structure. Minimal allocations and, dare we say, 🔥*blazingly* fast🔥.
## Features
- Zero dependencies
- Fast path matching with radix tree structure
- Support for path parameters (`[id]`) and wildcards (`*path`)
- Middleware support for request processing pipelines
- Route grouping with shared prefixes and middleware
- Implements `http.Handler` for direct integration
- Up to 15x faster than `http.ServeMux` for dynamic routes
- Zero allocations for static routes
## Installation
```shell
go get git.sharkk.net/Go/Router
```
## Usage
### Basic Routing
```go
// Create a new router
r := router.New()
// Static routes
r.Get("/", func(w router.Res, r router.Req, params []string) {
fmt.Fprintf(w, "Root handler")
})
// Parameter routes
r.Get("/users/[id]", func(w router.Res, r router.Req, params []string) {
userID := params[0]
fmt.Fprintf(w, "User ID: %s", userID)
})
// Wildcard routes
r.Get("/files/*path", func(w router.Res, r router.Req, params []string) {
filePath := params[0]
fmt.Fprintf(w, "File path: %s", filePath)
})
// Lookup routes manually
if handler, params, ok := r.Lookup("GET", "/users/123"); ok {
handler(nil, nil, params)
}
// Or simply serve them
http.ListenAndServe(":8080", r)
```
### Middleware
```go
// Create logging middleware
func LoggingMiddleware(next router.Handler) router.Handler {
return router.Handler(func(w router.Res, r router.Req, params []string) {
fmt.Println("Request started")
next(w, r, params)
fmt.Println("Request completed")
})
}
// Apply middleware globally
r := router.New()
r.Use(LoggingMiddleware)
// Apply middleware to specific routes
r.WithMiddleware(AuthMiddleware).Get("/admin", adminHandler)
http.ListenAndServe(":8080", r)
```
### Route Groups
```go
// Create a router
r := router.New()
// Create an API group
api := r.Group("/api")
api.Get("/users", listUsersHandler) // matches /api/users
// Nested groups
v1 := api.Group("/v1")
v1.Get("/products", listProductsHandler) // matches /api/v1/products
// Group with middleware
admin := api.Group("/admin")
admin.Use(AuthMiddleware)
admin.Get("/stats", statsHandler) // matches /api/admin/stats
http.ListenAndServe(":8080", r)
```
## Benchmarks
Benchmark comparing Router to the standard `http.ServeMux`:
```
cpu: 13th Gen Intel(R) Core(TM) i7-1370P
BenchmarkComparison/root_path
Router: 1.798 ns/op 0 B/op 0 allocs/op
ServeMux: 40.98 ns/op 0 B/op 0 allocs/op
BenchmarkComparison/static_path
Router: 18.41 ns/op 0 B/op 0 allocs/op
ServeMux: 86.04 ns/op 0 B/op 0 allocs/op
BenchmarkComparison/dynamic_path
Router: 24.23 ns/op 0 B/op 0 allocs/op
ServeMux: 221.9 ns/op 48 B/op 3 allocs/op
BenchmarkComparison/not_found
Router: 10.76 ns/op 0 B/op 0 allocs/op
ServeMux: 210.2 ns/op 56 B/op 3 allocs/op
```
- Root path lookups are 22x faster
- Static paths are 4.7x faster with zero allocations
- Dynamic paths are 9x faster with zero allocations
- Not found paths are 19.5x faster with zero allocations
## License
[Sharkk Minimal License](LICENSE); do what you like!