Skip to main content

Overview

The embed middleware provides helpers for serving files from Go’s embedded filesystem (embed.FS), enabling single-binary deployments. Use it when you need:
  • Single binary deployment
  • Bundled static assets
  • Embedded templates

Installation

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

Quick Start

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

app := mizu.New()
app.Use(embed.Static(staticFS, "static"))

Examples

Serve Static Files

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

app.Use(embed.Static(staticFS, "static"))
// Files at static/css/app.css available at /css/app.css

With Prefix

//go:embed assets/*
var assetsFS embed.FS

app.Use(embed.WithOptions(embed.Options{
    FS:     assetsFS,
    Root:   "assets",
    Prefix: "/assets",
}))
// /assets/js/app.js -> assets/js/app.js

Multiple Embeds

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

//go:embed templates/*
var templatesFS embed.FS

// Serve static files
app.Use(embed.Static(staticFS, "static"))

// Load templates
tmpl := embed.MustParseTemplates(templatesFS, "templates/*.html")

SPA with Embed

//go:embed dist/*
var distFS embed.FS

app.Use(embed.SPA(distFS, "dist"))

API Reference

Functions

// Static serves embedded static files
func Static(fs embed.FS, root string) mizu.Middleware

// SPA serves embedded SPA
func SPA(fs embed.FS, root string) mizu.Middleware

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

// Helper functions
func MustParseTemplates(fs embed.FS, pattern string) *template.Template
func ReadFile(fs embed.FS, name string) ([]byte, error)

Build Considerations

// Embed entire directory
//go:embed static/*

// Embed specific files
//go:embed favicon.ico robots.txt

// Embed with pattern
//go:embed templates/*.html templates/**/*.html

Technical Details

Implementation Overview

The embed middleware provides a bridge between Go’s embed.FS and Mizu’s HTTP serving capabilities. It wraps the standard library’s http.FileServer with additional features like custom root directories, caching headers, and SPA routing.

Core Components

Filesystem Handling
  • Uses fs.FS interface for maximum flexibility
  • Supports fs.Sub to create subdirectory filesystems
  • Falls back to original filesystem if subdirectory doesn’t exist
  • Implements proper path cleaning and normalization
File Serving Strategy
  1. Cleans and normalizes the request path
  2. Attempts to open the requested file
  3. Falls back to index file for directory requests
  4. Delegates to NotFoundHandler or next middleware if file not found
  5. Uses http.FileServer for actual serving (handles range requests, content-type, etc.)
Cache Control
  • Optional MaxAge setting for Cache-Control headers
  • Custom itoa function to avoid allocations for header values
  • Headers set before delegating to file server
SPA Support
  • Custom NotFoundHandler that serves index.html for missing routes
  • Preserves normal file serving for actual assets
  • Uses http.ServeContent for proper handling of conditional requests

Handler vs Middleware

The package provides both middleware and handler functions:
  • Middleware (New, WithOptions, Static, etc.): Falls through to next handler if file not found
  • Handler (Handler, HandlerWithOptions): Directly serves files without fallthrough

Best Practices

  • Use for production deployments
  • Keep embedded files small
  • Use content hashing for cache busting
  • Test embedded files in CI

Testing

The embed middleware includes comprehensive test coverage for all functionality:
Test CaseDescriptionExpected Behavior
TestNewBasic middleware creation and servingServes root index.html and nested files successfully
TestWithOptions_RootServing from a subdirectoryFiles from subdirectory accessible at root URL path
TestWithOptions_MaxAgeCache control headersCache-Control header set to specified max-age value
TestWithOptions_NotFoundHandlerCustom not found handlingCustom handler invoked for missing files with JSON response
TestHandlerDirect handler (non-middleware)Serves files without middleware chain
TestStaticStatic helper functionServes files from specified subdirectory
TestWithCachingCaching helper functionCache-Control header set correctly
TestIndexFileIndex file servingRoot and subdirectory index files served automatically
TestFallthroughMiddleware fallthroughNon-existent files fall through to next handler
TestSPASingle-page application modeExisting files served normally, unknown routes serve index.html
TestSPA_DefaultIndexSPA with default indexEmpty index parameter defaults to “index.html”
TestHandlerWithOptionsHandler with optionsOptions applied correctly in handler mode
TestHandlerWithOptions_RootHandler with custom rootFiles served from specified root directory
TestWithOptions_InvalidRootInvalid root directory handlingFalls back to original filesystem when root doesn’t exist
TestWithOptions_PathWithoutLeadingSlashPath normalizationPaths without leading slash handled correctly
TestItoaInteger to string conversionCustom itoa function converts integers correctly