FunctionStatic Files
ServeStatic
Serve static files from a directory with customizable URL prefix and efficient file handling.
Function Signature
func ServeStatic(prefix, dirpath string)Usage Examples
Basic Static File Serving
Serve files from a public directory.
func main() {
server := SpawnServer()
// Serve static files from "public" directory
// URL prefix: "/static"
// Directory: "./public"
server.ServeStatic("/static", "public")
// API routes
server.Get("/api/health", func(req *Request, res *Response) {
res.JSON(map[string]string{"status": "ok"})
res.Send()
})
server.Listen(":8080")
}
// Now you can access:
// http://localhost:8080/static/style.css -> serves ./public/style.css
// http://localhost:8080/static/js/app.js -> serves ./public/js/app.js
// http://localhost:8080/static/images/logo.png -> serves ./public/images/logo.pngMultiple Static Directories
Serve different types of static content from separate directories.
func main() {
server := SpawnServer()
// Serve CSS and JS assets
server.ServeStatic("/assets", "static/assets")
// Serve uploaded files
server.ServeStatic("/uploads", "storage/uploads")
// Serve documentation
server.ServeStatic("/docs", "documentation")
// Serve images with different prefix
server.ServeStatic("/media", "public/images")
server.Listen(":8080")
}
// Directory structure:
// static/assets/ -> /assets/*
// storage/uploads/ -> /uploads/*
// documentation/ -> /docs/*
// public/images/ -> /media/*SPA (Single Page Application) Setup
Serve a React/Vue/Angular app with fallback to index.html.
func main() {
server := SpawnServer()
// Serve static assets (CSS, JS, images)
server.ServeStatic("/static", "build/static")
// API routes
server.Get("/api/users", func(req *Request, res *Response) {
res.JSON([]map[string]string{
{"id": "1", "name": "John Doe"},
})
res.Send()
})
// Catch-all route for SPA (must be last)
server.Get("/*", func(req *Request, res *Response) {
// Serve index.html for all non-API routes
file, err := os.Open("build/index.html")
if err != nil {
res.SetStatus(404)
res.Write("Page not found")
res.Send()
return
}
defer file.Close()
res.SetHeader("Content-Type", "text/html")
res.SetBody(file)
res.Send()
})
server.Listen(":8080")
}
// This setup allows:
// /static/css/app.css -> serves build/static/css/app.css
// /static/js/app.js -> serves build/static/js/app.js
// / -> serves build/index.html
// /about -> serves build/index.html (SPA routing)
// /users/123 -> serves build/index.html (SPA routing)
// /api/users -> API response (not index.html)Static Files with Custom Headers
Add custom headers to static files using middleware.
func main() {
server := SpawnServer()
// Middleware for static file caching
staticCacheMiddleware := func(next HandlerFunc) HandlerFunc {
return func(req *Request, res *Response) {
// Only apply to static files
if strings.HasPrefix(req.Path, "/static/") {
// Set cache headers
res.SetHeader("Cache-Control", "public, max-age=31536000") // 1 year
res.SetHeader("Expires", time.Now().AddDate(1, 0, 0).Format(http.TimeFormat))
// Set security headers
res.SetHeader("X-Content-Type-Options", "nosniff")
// Set CORS headers for fonts/assets
if strings.HasSuffix(req.Path, ".woff2") ||
strings.HasSuffix(req.Path, ".woff") ||
strings.HasSuffix(req.Path, ".ttf") {
res.SetHeader("Access-Control-Allow-Origin", "*")
}
}
next(req, res)
}
}
// Apply middleware globally
server.Use(staticCacheMiddleware)
// Serve static files
server.ServeStatic("/static", "public")
server.Listen(":8080")
}File Upload and Serving
Handle file uploads and serve them statically.
import (
"io"
"os"
"path/filepath"
"strings"
)
func main() {
server := SpawnServer()
// Serve uploaded files
server.ServeStatic("/uploads", "storage/uploads")
// File upload endpoint
server.Post("/api/upload", func(req *Request, res *Response) {
// Read the uploaded file (simplified)
body, err := req.ReadBodyAsString()
if err != nil {
res.SetStatus(400)
res.JSON(map[string]string{"error": "Failed to read file"})
res.Send()
return
}
// Generate unique filename
filename := fmt.Sprintf("file_%d.txt", time.Now().UnixNano())
filepath := filepath.Join("storage/uploads", filename)
// Ensure upload directory exists
os.MkdirAll("storage/uploads", 0755)
// Save file
err = os.WriteFile(filepath, []byte(body), 0644)
if err != nil {
res.SetStatus(500)
res.JSON(map[string]string{"error": "Failed to save file"})
res.Send()
return
}
res.SetStatus(201)
res.JSON(map[string]string{
"message": "File uploaded successfully",
"filename": filename,
"url": "/uploads/" + filename,
})
res.Send()
})
// List uploaded files
server.Get("/api/files", func(req *Request, res *Response) {
files, err := os.ReadDir("storage/uploads")
if err != nil {
res.SetStatus(500)
res.JSON(map[string]string{"error": "Failed to read directory"})
res.Send()
return
}
var fileList []map[string]interface{}
for _, file := range files {
if !file.IsDir() {
info, _ := file.Info()
fileList = append(fileList, map[string]interface{}{
"name": file.Name(),
"size": info.Size(),
"url": "/uploads/" + file.Name(),
"modified": info.ModTime(),
})
}
}
res.JSON(map[string]interface{}{
"files": fileList,
"count": len(fileList),
})
res.Send()
})
server.Listen(":8080")
}Security Considerations
Important security practices when serving static files.
func main() {
server := SpawnServer()
// Security middleware for static files
secureStaticMiddleware := func(next HandlerFunc) HandlerFunc {
return func(req *Request, res *Response) {
// Only apply to static file routes
if strings.HasPrefix(req.Path, "/static/") {
// Prevent directory traversal attacks
if strings.Contains(req.Path, "..") {
res.SetStatus(403)
res.JSON(map[string]string{"error": "Forbidden"})
res.Send()
return
}
// Block access to sensitive files
blockedExtensions := []string{".env", ".config", ".key", ".pem"}
for _, ext := range blockedExtensions {
if strings.HasSuffix(req.Path, ext) {
res.SetStatus(403)
res.JSON(map[string]string{"error": "Access denied"})
res.Send()
return
}
}
// Set security headers
res.SetHeader("X-Content-Type-Options", "nosniff")
res.SetHeader("X-Frame-Options", "DENY")
res.SetHeader("Referrer-Policy", "strict-origin-when-cross-origin")
}
next(req, res)
}
}
server.Use(secureStaticMiddleware)
server.ServeStatic("/static", "public")
server.Listen(":8080")
}
// Security checklist for static files:
// ✅ Validate file paths to prevent directory traversal
// ✅ Block access to sensitive file types
// ✅ Set appropriate security headers
// ✅ Use HTTPS in production
// ✅ Implement proper file permissions
// ✅ Consider using a CDN for better performance and securityThe
ServeStatic function provides efficient static file serving with automatic MIME type detection. Always validate file paths and implement security measures to prevent directory traversal attacks and unauthorized access to sensitive files.