Skip to main content
Mizu provides a focused set of features for building web applications in Go. Each feature is designed to feel familiar if you already know Go’s standard library.

Routing

Routing connects URLs to handler functions. Mizu uses Go 1.22’s enhanced ServeMux which supports path parameters natively.
app.Get("/users/{id}", getUser)         // GET /users/123
app.Post("/users", createUser)          // POST /users
app.Delete("/users/{id}", deleteUser)   // DELETE /users/123
Key features:
  • Path parameters using {param} syntax (Go 1.22 ServeMux patterns)
  • HTTP method helpers: Get, Post, Put, Patch, Delete, Head, Connect, Trace
  • Route groups with Group() and Prefix() for organizing related endpoints
  • Scoped middleware with With() to apply middleware to specific routes
  • Mount http.Handler with Mount() for interoperability with standard handlers
// Group routes under a prefix
app.Group("/api", func(r *mizu.Router) {
    r.Get("/users", listUsers)      // GET /api/users
    r.Get("/users/{id}", getUser)   // GET /api/users/123
})

Request handling

Reading data from requests is explicit and straightforward. Each method does one thing clearly.
MethodPurposeExample
c.Param("id")Path parameter from URL/users/{id} → c.Param("id")
c.Query("page")Single query parameter?page=2 → c.Query("page")
c.QueryValues()All query parametersReturns url.Values
c.Form()Form data (POST)Returns url.Values, error
c.MultipartForm(max)File uploadsReturns form, cleanup, error
c.BindJSON(&v, max)JSON body to structValidates and parses
c.Cookie("name")Read a cookieReturns *http.Cookie, error
func getUser(c *mizu.Ctx) error {
    // Path parameter from /users/{id}
    id := c.Param("id")

    // Query parameter from ?include=email
    include := c.Query("include")

    return c.JSON(200, map[string]string{"id": id, "include": include})
}

Response helpers

Response methods write data with appropriate headers and status codes.
MethodContent-TypeUsage
c.Text(code, s)text/plainPlain text responses
c.JSON(code, v)application/jsonStructs, maps, slices
c.HTML(code, s)text/htmlHTML strings
c.File(code, path)Auto-detectedServe files from disk
c.Download(code, path, name)With dispositionForce download
c.Stream(fn)CustomStreaming responses
c.SSE(ch)text/event-streamServer-Sent Events
c.Redirect(code, url)-HTTP redirects
c.NoContent()-204 No Content
// Return JSON
return c.JSON(200, user)

// Serve a file with content-type auto-detection
return c.File(200, "./public/image.png")

// Force browser to download with a specific filename
return c.Download(200, "./reports/data.csv", "report-2024.csv")

Middleware

Middleware wraps handlers to add behavior before or after request processing. The pattern is simple: take a handler, return a handler.
type Middleware func(Handler) Handler
Applying middleware:
// Global middleware - runs for all routes
app.Use(myMiddleware)

// Scoped middleware - only for routes on this router
admin := app.With(authRequired)
admin.Get("/settings", adminSettings)

// Standard net/http middleware works too
app.Compat.Use(existingMiddleware)
Writing middleware:
func timing() mizu.Middleware {
    return func(next mizu.Handler) mizu.Handler {
        return func(c *mizu.Ctx) error {
            start := time.Now()
            err := next(c)
            c.Logger().Info("request", "duration", time.Since(start))
            return err
        }
    }
}

Logging

Mizu includes a request logger that uses Go’s slog package for structured logging.
// Built-in logger is enabled by default
app := mizu.New() // Includes Logger middleware

// Access the logger in any handler
c.Logger().Info("processing", "user_id", userID)

// Configure logging behavior
app.Use(mizu.Logger(mizu.LoggerOptions{
    Mode:      mizu.Dev,   // Dev (text) or Prod (JSON)
    Color:     true,       // Colored output for terminals
    UserAgent: true,       // Include User-Agent in logs
}))
Log modes:
  • mizu.Auto - Colored text for terminals, JSON for non-terminals (default)
  • mizu.Dev - Human-readable text format
  • mizu.Prod - JSON lines for log collectors

Error handling

Handlers return errors directly. Mizu catches returned errors and recovered panics in one central place.
// Handlers can return errors
func getUser(c *mizu.Ctx) error {
    user, err := findUser(c.Param("id"))
    if err != nil {
        return err // Caught by error handler
    }
    return c.JSON(200, user)
}

// Set a global error handler
app.ErrorHandler(func(c *mizu.Ctx, err error) {
    // Check for panics
    if perr, ok := err.(*mizu.PanicError); ok {
        c.Logger().Error("panic", "value", perr.Value)
    }
    c.JSON(500, map[string]string{"error": "internal error"})
})

Server lifecycle

Mizu handles graceful shutdown automatically. When your server receives SIGINT (Ctrl+C) or SIGTERM, it:
  1. Stops accepting new connections
  2. Waits for active requests to complete (up to timeout)
  3. Shuts down cleanly
app := mizu.New()

// Configure shutdown timeout (default: 15 seconds)
app.ShutdownTimeout = 30 * time.Second

// Start methods
app.Listen(":3000")                            // HTTP
app.ListenTLS(":443", "cert.pem", "key.pem")   // HTTPS
app.Serve(listener)                            // Custom listener
Health check endpoints for load balancers and Kubernetes:
// Liveness probe - always returns 200
http.Handle("/livez", app.LivezHandler())

// Readiness probe - returns 503 during shutdown
http.Handle("/readyz", app.ReadyzHandler())

Static files

Serve files from disk or embedded filesystems.
// Serve ./public folder at /assets
app.Static("/assets/", http.Dir("public"))
// Access: /assets/logo.png → ./public/logo.png

// Serve embedded files (Go 1.16+)
//go:embed public/*
var publicFS embed.FS

sub, _ := fs.Sub(publicFS, "public")
app.Static("/assets/", http.FS(sub))

Summary

Mizu stays small and predictable. Everything is plain Go code with no hidden behavior.
CategoryKey point
RoutingGo 1.22 ServeMux patterns with {param} syntax
RequestExplicit methods: Param, Query, Form, BindJSON
ResponseType helpers: Text, JSON, HTML, File, SSE
MiddlewareSimple func(Handler) Handler signature
LoggingBuilt-in with slog, configurable modes
ErrorsReturn from handlers, catch in one place
LifecycleGraceful shutdown with configurable timeout