Skip to main content

Overview

The static middleware serves static files from a directory or embedded filesystem. It supports index files, directory browsing, and cache control. Use it when you need:
  • Serve static assets (CSS, JS, images)
  • Serve a web application’s static files
  • Serve files from embedded filesystem

Installation

import "github.com/go-mizu/mizu/middlewares/static"

Quick Start

app := mizu.New()

// Serve files from ./public directory
app.Use(static.New("./public"))

// Or serve from embedded filesystem
//go:embed static/*
var staticFS embed.FS
app.Use(static.WithFS(staticFS))

Configuration

Options

OptionTypeDefaultDescription
RootstringRequiredRoot directory path
FSfs.FSnilFilesystem to serve from
Prefixstring""URL prefix for static files
Indexstring"index.html"Default index file
BrowseboolfalseEnable directory browsing
MaxAgeint0Cache-Control max-age in seconds
NotFoundHandlerfunc(*mizu.Ctx) errornilCustom 404 handler

Examples

Basic File Serving

app.Use(static.New("./public"))

With URL Prefix

app.Use(static.WithOptions(static.Options{
    Root:   "./public",
    Prefix: "/static",
}))
// Files available at /static/css/style.css, etc.

From Embedded Filesystem

//go:embed static/*
var staticFS embed.FS

app.Use(static.WithFS(staticFS))

With Cache Control

app.Use(static.WithOptions(static.Options{
    Root:   "./public",
    MaxAge: 86400, // 1 day
}))

Directory Browsing

app.Use(static.WithOptions(static.Options{
    Root:   "./files",
    Browse: true,
}))

Custom Index File

app.Use(static.WithOptions(static.Options{
    Root:  "./public",
    Index: "default.htm",
}))

Custom 404 Handler

app.Use(static.WithOptions(static.Options{
    Root: "./public",
    NotFoundHandler: func(c *mizu.Ctx) error {
        return c.Text(404, "File not found")
    },
}))

Multiple Static Directories

// Serve assets with prefix
app.Use(static.WithOptions(static.Options{
    Root:   "./assets",
    Prefix: "/assets",
}))

// Serve uploads with different prefix
app.Use(static.WithOptions(static.Options{
    Root:   "./uploads",
    Prefix: "/uploads",
}))

API Reference

Functions

// New creates static middleware for a directory
func New(root string) mizu.Middleware

// WithFS creates static middleware for an fs.FS
func WithFS(fsys fs.FS) mizu.Middleware

// WithOptions creates static middleware with full configuration
func WithOptions(opts Options) mizu.Middleware

Behavior

  • Falls through to next handler if file not found (unless NotFoundHandler set)
  • Automatically serves index.html for directory requests
  • Sets appropriate Content-Type based on file extension
  • Supports conditional requests with If-Modified-Since

Technical Details

Implementation Overview

The static middleware serves files from either a local filesystem directory or an embedded fs.FS interface. It implements intelligent path resolution and content serving with the following key features:

Path Resolution

  • Strips URL prefix if configured
  • Cleans and normalizes file paths using filepath.Clean
  • Converts URL paths to filesystem paths safely
  • Checks file existence before serving

File Serving Strategy

The middleware uses two different serving approaches:
  1. Direct File Serving (default)
    • Uses http.ServeContent for individual files
    • Provides proper Content-Type detection based on file extension
    • Supports HTTP range requests for partial content
    • Handles conditional requests with If-Modified-Since headers
    • Sets Last-Modified based on file modification time
  2. FileServer Mode (directory browsing enabled)
    • Uses http.FileServer when Browse: true
    • Generates HTML directory listings automatically
    • Ensures directory paths end with / to prevent redirects

Index File Handling

When a directory is requested:
  1. Checks if an index file exists (default: index.html)
  2. Serves the index file if found
  3. If not found and browsing disabled: calls NotFoundHandler or falls through to next middleware
  4. If not found and browsing enabled: shows directory listing

Cache Control

  • Sets Cache-Control: public, max-age=<seconds> when MaxAge > 0
  • No caching headers by default (MaxAge: 0)
  • Relies on HTTP standard caching mechanisms

Filesystem Abstraction

The middleware supports two filesystem sources:
  • FS (fs.FS): Takes precedence if set, ideal for embedded filesystems
  • Root (string): Uses OS filesystem with the specified root directory

Error Handling

  • Returns 404 for non-existent files (via custom handler or next middleware)
  • Returns 500 for internal file stat errors
  • Safely handles file close operations with deferred cleanup

Performance Optimizations

  • Custom itoa function to avoid allocations for Cache-Control header
  • Direct file serving without unnecessary FileServer overhead
  • Minimal path manipulation and string operations

Best Practices

  • Use embedded filesystem for portable deployments
  • Set appropriate MaxAge for caching static assets
  • Use versioned filenames for cache busting
  • Disable directory browsing in production

Testing

The static middleware includes comprehensive test coverage for all major functionality:
Test CaseDescriptionExpected Behavior
TestNew/serve fileServes a regular file from filesystemReturns 200 OK with correct file content
TestNew/serve indexServes index.html for root directory requestReturns 200 OK with index.html content
TestNew/file not found falls throughHandles missing files when no NotFoundHandler setFalls through to next middleware handler
TestWithFS/serve file from FSServes files from fs.FS interfaceReturns 200 OK with file content from embedded FS
TestWithOptions_Prefix/with prefixServes files with URL prefix strippedReturns 200 OK for paths matching prefix
TestWithOptions_Prefix/without prefix falls throughHandles requests not matching prefixFalls through to next middleware
TestWithOptions_MaxAgeSets cache control headersReturns Cache-Control header with max-age value
TestWithOptions_NotFoundHandlerUses custom 404 handler for missing filesCalls custom handler returning custom 404 response
TestWithOptions_CustomIndexServes custom index file (e.g., default.htm)Returns 200 OK with custom index file content
TestWithOptions_BrowseEnables directory browsingReturns 200 OK with directory listing HTML
TestWithOptions_PanicsValidates configuration on creationPanics when neither FS nor Root is provided
  • spa - Single Page Application support
  • favicon - Favicon serving
  • embed - Embedded filesystem helpers
  • cache - Cache control headers