dream/controllers/static
Secure static file serving
Serve files from disk with built-in security. Handles CSS, JavaScript, images, and any other static assets your application needs.
Quick Setup
import dream/controllers/static.{default_config, serve}
import dream/http/request.{type Request, Get, get_string_param}
import dream/http/response.{type Response, json_response}
import dream/http/status.{bad_request}
import dream/router.{route}
pub fn serve_assets(request: Request, context, services) -> Response {
case get_string_param(request, "path") {
Ok(path) ->
serve(
request: request,
context: context,
services: services,
root: "./public",
filepath: path,
config: default_config(),
)
Error(msg) -> json_response(bad_request, error_json(msg))
}
}
// In your router:
route(method: Get, path: "/assets/**path", controller: serve_assets, middleware: [])
Security
Built-in protection against:
- Path traversal attacks (
../../../etc/passwd) - Absolute path access (
/etc/passwd) - Directory escaping
Files outside the root directory return 404, never errors that reveal filesystem structure.
Features
- MIME type detection - Automatic content-type headers
- Index serving - Serves
index.htmlfor directory requests - Directory listing - Optional file browser (disabled by default)
- Custom 404s - Use your own not-found handler Control how directories and missing files are handled.
- Serves
index.htmlfor directories - No directory listing
- Standard 404 response for missing files
Shows a file browser when a directory has no
index.html. Use this for development or when you want users to browse files. Don’t enable in production unless you specifically want directory browsing.
Types
Configuration for static file serving
pub type Config(context, services) {
Config(
serve_index: Bool,
allow_directory_listing: Bool,
not_found_handler: option.Option(
fn(request.Request, context, services) -> response.Response,
),
)
}
Constructors
-
Config( serve_index: Bool, allow_directory_listing: Bool, not_found_handler: option.Option( fn(request.Request, context, services) -> response.Response, ), )Arguments
- serve_index
-
Whether to serve index.html for directory requests
- allow_directory_listing
-
Whether to allow directory listing when no index.html exists
- not_found_handler
-
Custom 404 handler (None = default 404 response)
Values
pub fn default_config() -> Config(context, services)
Default configuration with secure settings
pub fn serve(
request request: request.Request,
context context: context,
services services: services,
root root: String,
filepath filepath: String,
config config: Config(context, services),
) -> response.Response
Serve static files from a directory
Security:
- Prevents path traversal attacks (../)
- Validates paths stay within root directory
- Returns 404 for files outside root
Usage:
import dream/controllers/static.{default_config, serve}
import dream/http/request.{type Request, get_string_param}
import dream/http/response.{type Response, json_response}
import dream/http/status.{bad_request}
pub fn serve_public(request: Request, context, services) -> Response {
case get_string_param(request, "filepath") {
Ok(filepath) ->
serve(
request: request,
context: context,
services: services,
root: "./public",
filepath: filepath,
config: default_config(),
)
Error(msg) -> json_response(bad_request, error_json(msg))
}
}
pub fn with_custom_404(
config: Config(context, services),
handler: fn(request.Request, context, services) -> response.Response,
) -> Config(context, services)
Set custom 404 handler
pub fn with_directory_listing(
config: Config(context, services),
) -> Config(context, services)
Enable directory listing