Routing Guide
Learn how to define routes, handle path parameters, and organize your applications URL structure with Squirrel.
RoutingHTTP MethodsPath Parameters
Basic Routing
Define simple routes to handle different URL paths
package main
import (
"fmt"
"net/http"
"github.com/squirrel-land/squirrel"
)
func main() {
mux := squirrel.NewSqurlMux()
// Basic routes
mux.HandleFunc("/", homeHandler)
mux.HandleFunc("/about", aboutHandler)
mux.HandleFunc("/contact", contactHandler)
http.ListenAndServe(":8080", mux)
}
func homeHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Welcome to the home page!")
}
func aboutHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "About us page")
}
func contactHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Contact us at contact@example.com")
}Path Parameters
Capture dynamic values from URL paths
package main
import (
"fmt"
"net/http"
"github.com/squirrel-land/squirrel"
)
func main() {
mux := squirrel.NewSqurlMux()
// Single parameter
mux.HandleFunc("/user/{id}", userHandler)
// Multiple parameters
mux.HandleFunc("/user/{id}/post/{postId}", postHandler)
// Optional parameters with wildcards
mux.HandleFunc("/files/{path...}", fileHandler)
http.ListenAndServe(":8080", mux)
}
func userHandler(w http.ResponseWriter, r *http.Request) {
id := squirrel.GetParam(r, "id")
fmt.Fprintf(w, "User ID: %s", id)
}
func postHandler(w http.ResponseWriter, r *http.Request) {
userID := squirrel.GetParam(r, "id")
postID := squirrel.GetParam(r, "postId")
fmt.Fprintf(w, "User %s, Post %s", userID, postID)
}
func fileHandler(w http.ResponseWriter, r *http.Request) {
path := squirrel.GetParam(r, "path")
fmt.Fprintf(w, "File path: %s", path)
}HTTP Methods
Handle different HTTP methods (GET, POST, PUT, DELETE, etc.)
package main
import (
"encoding/json"
"fmt"
"net/http"
"github.com/squirrel-land/squirrel"
)
func main() {
mux := squirrel.NewSqurlMux()
// Method-specific routes
mux.Get("/users", getUsersHandler)
mux.Post("/users", createUserHandler)
mux.Put("/users/{id}", updateUserHandler)
mux.Delete("/users/{id}", deleteUserHandler)
// Generic handler with method checking
mux.HandleFunc("/api/status", func(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodGet:
fmt.Fprintf(w, "Status: OK")
case http.MethodPost:
fmt.Fprintf(w, "Status updated")
default:
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
}
})
http.ListenAndServe(":8080", mux)
}
func getUsersHandler(w http.ResponseWriter, r *http.Request) {
users := []string{"Alice", "Bob", "Charlie"}
json.NewEncoder(w).Encode(users)
}
func createUserHandler(w http.ResponseWriter, r *http.Request) {
// Handle user creation
w.WriteHeader(http.StatusCreated)
fmt.Fprintf(w, "User created")
}
func updateUserHandler(w http.ResponseWriter, r *http.Request) {
id := squirrel.GetParam(r, "id")
fmt.Fprintf(w, "User %s updated", id)
}
func deleteUserHandler(w http.ResponseWriter, r *http.Request) {
id := squirrel.GetParam(r, "id")
fmt.Fprintf(w, "User %s deleted", id)
}Route Groups
Organize related routes with common prefixes and middleware
package main
import (
"fmt"
"net/http"
"github.com/squirrel-land/squirrel"
)
func main() {
mux := squirrel.NewSqurlMux()
// API v1 routes
apiV1 := mux.Group("/api/v1")
apiV1.Use(authMiddleware) // Apply middleware to all routes in group
apiV1.Get("/users", getUsersHandler)
apiV1.Post("/users", createUserHandler)
apiV1.Get("/posts", getPostsHandler)
// API v2 routes
apiV2 := mux.Group("/api/v2")
apiV2.Use(authMiddleware)
apiV2.Use(rateLimitMiddleware)
apiV2.Get("/users", getUsersV2Handler)
apiV2.Post("/users", createUserV2Handler)
// Admin routes
admin := mux.Group("/admin")
admin.Use(adminAuthMiddleware)
admin.Get("/dashboard", adminDashboardHandler)
admin.Get("/users", adminUsersHandler)
http.ListenAndServe(":8080", mux)
}
func authMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Check authentication
token := r.Header.Get("Authorization")
if token == "" {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
next.ServeHTTP(w, r)
})
}Best Practice: Use route groups to organize your API endpoints and apply common middleware. This keeps your code clean and makes it easier to manage authentication, rate limiting, and other cross-cutting concerns.
Advanced Routing Patterns
Complex routing scenarios and best practices
// Subdomain routing
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
host := r.Host
switch {
case strings.HasPrefix(host, "api."):
apiHandler(w, r)
case strings.HasPrefix(host, "admin."):
adminHandler(w, r)
default:
mainSiteHandler(w, r)
}
})