Intake is a lightweight, flexible HTTP router for Go applications with middleware support. It provides a simple API for defining routes, handling requests, and applying middleware.
- Simple and intuitive API for defining HTTP routes
- Middleware support for request pre-processing and post-processing
- Chainable middleware for both global and route-specific use
- Convenient response helpers for JSON, XML, and raw data
- Support for all standard HTTP methods (GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS)
- Bulk operations for managing multiple endpoints as a group
- Graceful shutdown support
- Minimal dependencies
go get github.com/dbubel/intake/v2
package main
import (
"fmt"
"net/http"
"time"
"github.com/dbubel/intake/v2"
)
func main() {
// Create a new Intake instance
app := intake.New()
// Define a simple handler
helloHandler := func(w http.ResponseWriter, r *http.Request) {
intake.Respond(w, r, http.StatusOK, []byte("Hello, World!"))
}
// Add a route
app.AddEndpoint(http.MethodGet, "/hello", helloHandler)
// Start the server with graceful shutdown
app.Run(&http.Server{
Addr: ":8080",
Handler: app.Mux,
ReadTimeout: time.Second * 60,
WriteTimeout: time.Second * 60,
MaxHeaderBytes: 1 << 20,
})
}
Intake provides a flexible middleware system that allows you to intercept and process requests before they reach your handlers.
Middleware in Intake is defined as a function that takes an http.HandlerFunc
and returns an http.HandlerFunc
:
func loggingMiddleware(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// Do something before the handler
fmt.Println("Request received:", r.Method, r.URL.Path)
// Call the next handler
next(w, r)
// Do something after the handler
fmt.Println("Response sent")
}
}
Global middleware is applied to all routes:
app.AddGlobalMiddleware(loggingMiddleware)
You can add middleware to specific routes:
app.AddEndpoint(http.MethodGet, "/protected", protectedHandler, authMiddleware)
Middleware can be chained together:
app.AddEndpoint(http.MethodGet, "/api/data", dataHandler,
loggingMiddleware,
authMiddleware,
rateLimitMiddleware)
Intake provides helper functions for creating endpoints with specific HTTP methods:
// These all create endpoint objects
getEndpoint := intake.GET("/users", listUsersHandler)
postEndpoint := intake.POST("/users", createUserHandler)
putEndpoint := intake.PUT("/users/:id", updateUserHandler)
deleteEndpoint := intake.DELETE("/users/:id", deleteUserHandler)
You can group endpoints together to apply middleware to all of them:
// Create a group of endpoints
apiEndpoints := intake.Endpoints{
intake.GET("/api/users", listUsersHandler),
intake.POST("/api/users", createUserHandler),
intake.GET("/api/products", listProductsHandler),
}
// Apply middleware to all endpoints in the group
apiEndpoints.Use(authMiddleware)
// Add all endpoints to the app
app.AddEndpoints(apiEndpoints)
You can control the order of middleware execution:
// Add middleware to the end of the chain
endpoints.Append(loggingMiddleware)
// Add middleware to the beginning of the chain (after global middleware)
endpoints.Prepend(metricMiddleware)
Intake provides helper functions for common response types:
// JSON response
intake.RespondJSON(w, r, http.StatusOK, data)
// XML response
intake.RespondXML(w, r, http.StatusOK, data)
// Raw response
intake.Respond(w, r, http.StatusOK, []byte("Hello, World!"))
Intake makes it easy to handle OPTIONS requests for CORS:
app.OptionsHandler(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
w.Header().Set("Access-Control-Allow-Headers", "Origin, Content-Type, Content-Length, Accept-Encoding, Authorization")
w.WriteHeader(http.StatusOK)
})
package main
import (
"fmt"
"net/http"
"time"
"github.com/dbubel/intake/v2"
)
func main() {
app := intake.New()
// Define middleware
loggingMiddleware := func(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
fmt.Println("Request received:", r.Method, r.URL.Path)
next(w, r)
fmt.Println("Response sent")
}
}
// Add global middleware
app.AddGlobalMiddleware(loggingMiddleware)
// Define handlers
helloHandler := func(w http.ResponseWriter, r *http.Request) {
intake.RespondJSON(w, r, http.StatusOK, map[string]string{
"message": "Hello, World!",
})
}
userHandler := func(w http.ResponseWriter, r *http.Request) {
intake.RespondJSON(w, r, http.StatusOK, map[string]string{
"user": "John Doe",
})
}
// Define OPTIONS handler
app.OptionsHandler(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
w.Header().Set("Access-Control-Allow-Headers", "Origin, Content-Type, Content-Length, Accept-Encoding, Authorization")
w.WriteHeader(http.StatusOK)
})
// Create endpoints
apiEndpoints := intake.Endpoints{
intake.GET("/api/hello", helloHandler),
intake.GET("/api/user", userHandler),
}
// Add endpoints to the app
app.AddEndpoints(apiEndpoints)
// Add a single endpoint
app.AddEndpoint(http.MethodGet, "/health", func(w http.ResponseWriter, r *http.Request) {
intake.RespondJSON(w, r, http.StatusOK, map[string]string{
"status": "healthy",
})
})
// Print registered routes
routes := app.GetRoutes()
fmt.Println("Registered routes:")
for path, methods := range routes {
fmt.Printf("%s: %v\n", path, methods)
}
// Start the server
fmt.Println("Server starting on :8080")
app.Run(&http.Server{
Addr: ":8080",
Handler: app.Mux,
ReadTimeout: time.Second * 60,
WriteTimeout: time.Second * 60,
MaxHeaderBytes: 1 << 20,
})
}
## License
MIT
## Contributing
Contributions are welcome! Please feel free to submit a Pull Request.