Files
mux/QUICKSTART.md

330 lines
7.0 KiB
Markdown
Raw Normal View History

# Quick Start Guide
Get up and running with Mux in under 5 minutes!
## Installation
```bash
go get code.patial.tech/go/mux
```
## Requirements
- Go 1.25 or higher
## Your First Route
Create `main.go`:
```go
package main
import (
"fmt"
"net/http"
"code.patial.tech/go/mux"
)
func main() {
m := mux.New()
m.GET("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Hello, Mux!")
})
m.Serve(func(srv *http.Server) error {
srv.Addr = ":8080"
fmt.Println("Server listening on http://localhost:8080")
return srv.ListenAndServe()
})
}
```
Run it:
```bash
go run main.go
```
Visit [http://localhost:8080](http://localhost:8080) 🎉
## Common Patterns
### 1. Multiple Routes
```go
m := mux.New()
m.GET("/", homeHandler)
m.GET("/about", aboutHandler)
m.GET("/users/{id}", showUser)
m.POST("/users", createUser)
```
### 2. Using Middleware
```go
m := mux.New()
// Add global middleware
m.Use(loggingMiddleware)
m.Use(authMiddleware)
// All routes will use both middleware
m.GET("/protected", protectedHandler)
```
### 3. Route Groups
```go
m := mux.New()
// Public routes
m.GET("/", homeHandler)
// API routes with shared middleware
m.Group(func(api *mux.Mux) {
api.Use(jsonMiddleware)
api.Use(apiAuthMiddleware)
api.GET("/api/users", listUsers)
api.POST("/api/users", createUser)
})
```
### 4. RESTful Resources
```go
m := mux.New()
m.Resource("/posts", func(res *mux.Resource) {
res.Index(listPosts) // GET /posts
res.Create(createPost) // POST /posts
res.View(showPost) // GET /posts/{id}
res.Update(updatePost) // PUT /posts/{id}
res.Delete(deletePost) // DELETE /posts/{id}
// Custom collection routes
res.POST("/search", searchPosts) // POST /posts/search
// Custom member routes
res.MemberPOST("/publish", publishPost) // POST /posts/{id}/publish
})
```
### 5. URL Parameters
```go
m.GET("/users/{id}", func(w http.ResponseWriter, r *http.Request) {
userID := r.PathValue("id")
fmt.Fprintf(w, "User ID: %s", userID)
})
m.GET("/posts/{year}/{month}/{slug}", func(w http.ResponseWriter, r *http.Request) {
year := r.PathValue("year")
month := r.PathValue("month")
slug := r.PathValue("slug")
// Handle request...
})
```
## Complete Example
Here's a more complete example:
```go
package main
import (
"encoding/json"
"fmt"
"log/slog"
"net/http"
"time"
"code.patial.tech/go/mux"
)
func main() {
m := mux.New()
// Global middleware
m.Use(loggingMiddleware)
// Routes
m.GET("/", homeHandler)
m.GET("/health", healthHandler)
// API group
m.Group(func(api *mux.Mux) {
api.Use(jsonMiddleware)
// Users resource
api.Resource("/users", func(res *mux.Resource) {
res.Index(listUsers)
res.Create(createUser)
res.View(showUser)
res.Update(updateUser)
res.Delete(deleteUser)
// Custom routes
res.POST("/search", searchUsers)
res.MemberGET("/posts", getUserPosts)
})
})
// Debug routes
m.GET("/debug/routes", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/plain")
m.PrintRoutes(w)
})
// Start server
m.Serve(func(srv *http.Server) error {
srv.Addr = ":8080"
srv.ReadTimeout = 30 * time.Second
srv.WriteTimeout = 30 * time.Second
slog.Info("Server starting", "addr", srv.Addr)
return srv.ListenAndServe()
})
}
// Middleware
func loggingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
next.ServeHTTP(w, r)
slog.Info("request",
"method", r.Method,
"path", r.URL.Path,
"duration", time.Since(start))
})
}
func jsonMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
next.ServeHTTP(w, r)
})
}
// Handlers
func homeHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Welcome to Mux!")
}
func healthHandler(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(map[string]string{"status": "ok"})
}
func listUsers(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(map[string][]string{"users": {}})
}
func createUser(w http.ResponseWriter, r *http.Request) {
// Parse request body and create user
json.NewEncoder(w).Encode(map[string]string{"message": "User created"})
}
func showUser(w http.ResponseWriter, r *http.Request) {
id := r.PathValue("id")
json.NewEncoder(w).Encode(map[string]string{"id": id, "name": "John Doe"})
}
func updateUser(w http.ResponseWriter, r *http.Request) {
id := r.PathValue("id")
json.NewEncoder(w).Encode(map[string]string{"message": fmt.Sprintf("User %s updated", id)})
}
func deleteUser(w http.ResponseWriter, r *http.Request) {
id := r.PathValue("id")
json.NewEncoder(w).Encode(map[string]string{"message": fmt.Sprintf("User %s deleted", id)})
}
func searchUsers(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(map[string][]string{"results": {}})
}
func getUserPosts(w http.ResponseWriter, r *http.Request) {
id := r.PathValue("id")
json.NewEncoder(w).Encode(map[string]interface{}{
"user_id": id,
"posts": []string{},
})
}
```
## Next Steps
- Read the [full README](README.md) for detailed documentation
- Check [CONTRIBUTING.md](CONTRIBUTING.md) for code quality standards
- Look at the [example directory](example/) for more examples
- Review the [middleware package](middleware/) for built-in middleware
## Testing Your Routes
```go
package main
import (
"net/http"
"net/http/httptest"
"testing"
"code.patial.tech/go/mux"
)
func TestHomeHandler(t *testing.T) {
m := mux.New()
m.GET("/", homeHandler)
req := httptest.NewRequest(http.MethodGet, "/", nil)
rec := httptest.NewRecorder()
m.ServeHTTP(rec, req)
if rec.Code != http.StatusOK {
t.Errorf("expected status 200, got %d", rec.Code)
}
}
```
## Common Issues
### Port Already in Use
If you see "address already in use", change the port:
```go
srv.Addr = ":8081" // Use a different port
```
### 404 Not Found
Make sure your route patterns start with `/`:
```go
m.GET("/users", handler) // ✅ Correct
m.GET("users", handler) // ❌ Wrong
```
### Middleware Not Working
Ensure middleware is registered before routes:
```go
m.Use(middleware1) // ✅ Register first
m.GET("/route", handler) // Then add routes
```
## Getting Help
- Check the [README](README.md) for detailed documentation
- Look at [examples](example/) for working code
- Open an issue on GitHub for bugs or questions
---
Happy routing! 🚀