Inspired by Hono.js, built for performance and simplicity.
Amaro is a lightweight, high-performance web framework for Go. It prioritizes zero allocations in the hot path, zero external dependencies, and a developer-friendly API that feels like modern JavaScript frameworks but with the power of Go.
- Zero Dependency: Runs on pure Go standard library.
- Blazing Fast: Optimized Trie-based router with zero-allocation context pooling.
- Decoupled Architecture: Router implementation is fully decoupled from the core framework.
- Configurable Syntax: Support for customizable parameter delimiters (e.g.
:idor{id}) via pluggable parsers. - Robust Static Serving: Built-in support for serving static files, SPAs, and directory browsing (configurable).
- Production-Grade Middlewares: Includes Auth (Basic, Key, Session, RBAC), CORS, Cache, and more.
- Group Routing: Organize routes with prefixes and shared middlewares.
- Context Pooling: Reuses request contexts to minimize GC pressure.
- Addon System: Extensible with powerful addons like OpenAPI generation and Streaming.
go get github.com/buildwithgo/amaropackage main
import (
"net/http"
"github.com/buildwithgo/amaro"
"github.com/buildwithgo/amaro/routers"
)
func main() {
// Initialize with the optimized TrieRouter
app := amaro.New(amaro.WithRouter(routers.NewTrieRouter()))
app.GET("/", func(c *amaro.Context) error {
return c.String(http.StatusOK, "Hello, Amaro! π₯")
})
app.GET("/json", func(c *amaro.Context) error {
return c.JSON(http.StatusOK, map[string]string{
"message": "Blazing fast JSON",
})
})
app.Run("8080")
}Amaro's TrieRouter is fully decoupled from the syntax it parses. You can define custom rules for identifying parameters using ParamParser functions.
// Custom parser for <id> syntax
customParser := func(segment string) (bool, string) {
if len(segment) > 2 && segment[0] == '<' && segment[len(segment)-1] == '>' {
return true, segment[1 : len(segment)-1]
}
return false, ""
}
config := routers.DefaultTrieRouterConfig()
config.ParamParser = customParser
r := routers.NewTrieRouter(routers.WithConfig(config))
app := amaro.New(amaro.WithRouter(r))
app.GET("/users/<id>", handler) // Matches /users/123Serve static files with robust support for SPAs (Single Page Applications).
app.StaticFS("/assets", os.DirFS("./public"))
// Or using the robust Static handler manually for more control
app.GET("/app/*filepath", amaro.StaticHandler(amaro.StaticConfig{
Root: os.DirFS("./dist"),
SPA: true, // Serve index.html on 404
Index: "index.html",
}))Amaro comes with a suite of production-grade middlewares.
import "github.com/buildwithgo/amaro/middlewares"
// Basic Auth
app.Use(middlewares.BasicAuth(func(user, pass string, c *amaro.Context) (bool, error) {
return user == "admin" && pass == "secret", nil
}))
// API Key Auth
app.Use(middlewares.KeyAuth(func(key string, c *amaro.Context) (bool, error) {
return key == "valid-api-key", nil
}))
// Session Auth (requires addons/sessions)
app.Use(middlewares.SessionAuth[User](validatorFunc))
// RBAC (Role-Based Access Control)
app.GET("/admin", middlewares.RBAC("admin", roleExtractor), adminHandler)// CORS with options
app.Use(middlewares.CORS(middlewares.CORSConfig{
AllowOrigins: []string{"https://example.com"},
AllowCredentials: true,
}))
// Cache responses
store := cache.NewMemoryCache()
app.GET("/cached-data", middlewares.CachePage(store, 5*time.Minute), handler)app.GET("/user/:id", func(c *amaro.Context) error {
id := c.PathParam("id") // Works with :id or {id} or configured syntax
return c.String(200, "User ID: "+id)
})// GET /search?q=golang
app.GET("/search", func(c *amaro.Context) error {
query := c.QueryParam("q")
return c.String(200, "Searching for: "+query)
})Amaro includes a built-in OpenAPI v3 generator to automatically document your API.
import "github.com/buildwithgo/amaro/addons/openapi"
// Create generator
gen := openapi.NewGenerator(openapi.Info{
Title: "My API",
Version: "1.0.0",
})
// ... (see full docs for usage)Contributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the MIT License - see the license file for details.