Skip to main content

Static Files with Functional Routing

Serve static assets (CSS, JavaScript, images, fonts, etc.) directly from a folder with automatic MIME type detection and caching headers.

When to Use Static File Routing​

  • Assets Folder - Serve CSS, JS, images from a /public or /assets folder
  • Single Entry Point - All requests go through index.php, including static files
  • Development Server - Using PHP's built-in server without separate static file handling
  • Simple Hosting - Environments without sophisticated web server configuration

Basic Usage​

<?php
require_once 'vendor/autoload.php';

router(function() {
// Serve static files from /public folder at /static URL
static_folder(__DIR__ . '/public', '/static');

// Other routes
route(method(GET), url_path('/'), function() {
echo 'Home';
});
});

URL Mapping​

The static_folder() function maps URL paths to files in your static folder:

/public/
├── css/
│ └── style.css → /static/css/style.css
├── js/
│ └── app.js → /static/js/app.js
├── images/
│ └── logo.png → /static/images/logo.png
└── fonts/
└── roboto.woff2 → /static/fonts/roboto.woff2
// All files in /public are served at /static/*
static_folder(__DIR__ . '/public', '/static');

Options​

Cache Control​

By default, static files are cached for 24 hours (86400 seconds). You can customize this:

// Cache for 1 week
static_folder(__DIR__ . '/public', '/static', array(
'cache_time' => 604800
));

// No caching (development)
static_folder(__DIR__ . '/public', '/static', array(
'cache_time' => 0
));

// Cache for 1 year (versioned assets)
static_folder(__DIR__ . '/public', '/static', array(
'cache_time' => 31536000
));

Allowed Extensions​

Restrict which file types can be served:

// Only serve CSS, JS, and images
static_folder(__DIR__ . '/public', '/static', array(
'allowed_extensions' => array('css', 'js', 'png', 'jpg', 'gif', 'svg', 'webp')
));

// Only serve fonts
static_folder(__DIR__ . '/fonts', '/fonts', array(
'allowed_extensions' => array('woff', 'woff2', 'ttf', 'otf', 'eot')
));

Multiple Static Folders​

router(function() {
// Serve different asset types from different folders
static_folder(__DIR__ . '/assets/css', '/css');
static_folder(__DIR__ . '/assets/js', '/js');
static_folder(__DIR__ . '/assets/images', '/images');
static_folder(__DIR__ . '/node_modules', '/vendor', array(
'allowed_extensions' => array('css', 'js', 'map')
));

// Application routes
route(method(GET), url_path('/'), function() {
echo 'Home';
});
});

Project Structure Example​

/project
├── index.php
├── public/
│ ├── css/
│ │ └── style.css
│ ├── js/
│ │ └── app.js
│ └── images/
│ └── logo.png
└── vendor/
// index.php
<?php
require_once 'vendor/autoload.php';

router(function() {
static_folder(__DIR__ . '/public', '/public');

route(method(GET), url_path('/'), function() {
echo html_response('<link rel="stylesheet" href="/public/css/style.css">');
});
});

Security​

The static_folder() function includes security measures:

Directory Traversal Prevention​

Attempts to access files outside the static folder are blocked:

// This will NOT serve files outside /public
// URL: /static/../../../etc/passwd
static_folder(__DIR__ . '/public', '/static');
// Result: 404 Not Found

Real Path Validation​

The function uses realpath() to resolve symbolic links and ensure files are within the allowed folder.

MIME Types​

The router automatically detects MIME types based on file extension. Common types include:

ExtensionMIME Type
.csstext/css
.jstext/javascript
.jsonapplication/json
.pngimage/png
.jpgimage/jpeg
.svgimage/svg+xml
.woff2font/woff2

You can also use mime_type() directly:

echo mime_type('css');   // text/css
echo mime_type('png'); // image/png
echo mime_type('woff2'); // font/woff2

Production Web Server​

For production, configure your web server to serve static files directly for better performance.

Apache​

RewriteEngine On

# If the file exists, serve it directly
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^public/(.*)$ public/$1 [L]

# Otherwise, route to PHP
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]

Nginx​

location /static {
alias /var/www/html/public;
expires 1y;
add_header Cache-Control "public, immutable";
}

location / {
try_files $uri /index.php?url=$uri&$args;
}