A module for serving static files with etags, caching, gzip compression, CORS support, and directory indexing.
—
Comprehensive configuration system supporting caching, security, performance, and behavior customization for the st static file server.
Core configuration options for the st static file server.
interface StOptions {
/** Filesystem path to serve files from (required) */
path: string;
/** URL mount point (default: '/') */
url?: string;
/** Directory indexing behavior - true for auto-index, false to disable, string for specific index file */
index?: boolean | string;
/** Allow serving dot files (default: false) */
dot?: boolean;
/** Pass through to next handler on 404 instead of returning error (default: false) */
passthrough?: boolean;
/** Enable gzip compression (default: true) */
gzip?: boolean;
/** Enable CORS headers (default: false) */
cors?: boolean;
/** Add X-From-Cache header for cached responses (default: false) */
cachedHeader?: boolean;
/** Cache configuration object or false to disable caching */
cache?: CacheOptions | false;
}Usage Examples:
const st = require('st');
// Basic configuration
const basicHandler = st({
path: './public',
url: '/static'
});
// Security-focused configuration
const secureHandler = st({
path: './secure',
dot: false, // Block dot files
passthrough: true, // Let app handle 404s
cors: false // No cross-origin access
});
// Performance-optimized configuration
const fastHandler = st({
path: './assets',
gzip: true,
cachedHeader: true,
cache: {
content: {
maxSize: 1024 * 1024 * 128, // 128MB cache
maxAge: 1000 * 60 * 30 // 30 minute cache
}
}
});Filesystem path configuration and behavior.
/**
* Required filesystem path to serve files from
* - Must be a string
* - Will be resolved to absolute path
* - Must exist and be accessible
*/
path: string;Usage Example:
// Relative path (resolved against process.cwd())
const handler1 = st({ path: './static' });
// Absolute path
const handler2 = st({ path: '/var/www/html' });
// Using path module for cross-platform compatibility
const path = require('path');
const handler3 = st({
path: path.join(__dirname, 'public')
});URL mounting configuration for serving files at specific paths.
/**
* URL mount point where files will be served
* - Default: '/'
* - Must start with '/'
* - Example: '/static' serves files at /static/file.js
*/
url?: string;Usage Example:
// Serve at root (default)
const rootHandler = st({ path: './public' });
// Serve at /static
const staticHandler = st({
path: './assets',
url: '/static'
});
// Serve at nested path
const nestedHandler = st({
path: './images',
url: '/assets/images'
});Configuration for directory listing and index file behavior.
/**
* Directory indexing behavior
* - true: Enable auto-indexing (generates HTML directory listings)
* - false: Return 404 for directory requests
* - string: Use specific file as index (e.g., 'index.html')
*/
index?: boolean | string;Usage Examples:
// Auto-indexing enabled (shows directory listings)
const autoIndexHandler = st({
path: './files',
index: true
});
// Use specific index file
const htmlIndexHandler = st({
path: './website',
index: 'index.html'
});
// Disable directory access entirely
const noIndexHandler = st({
path: './api-only',
index: false
});Security-related configuration options.
/**
* Dot file access control
* - false: Return 403 for any URL with dot-file part (default)
* - true: Allow dot-files to be served normally
*/
dot?: boolean;
/**
* Passthrough behavior for unhandled requests
* - false: Return 404 when file not found (default)
* - true: Call next() or return false for middleware chains
*/
passthrough?: boolean;Usage Examples:
// Secure configuration - block dot files
const secureHandler = st({
path: './public',
dot: false // Blocks .htaccess, .env, etc.
});
// Development configuration - allow dot files
const devHandler = st({
path: './dev-files',
dot: true // Allows .well-known, etc.
});
// Middleware-friendly configuration
const middlewareHandler = st({
path: './assets',
passthrough: true // Falls through to next handler
});
// Use with Express-style middleware
app.use((req, res, next) => {
middlewareHandler(req, res, next);
});Performance and compression configuration.
/**
* Gzip compression
* - true: Enable gzip compression for supported files (default)
* - false: Disable compression entirely
*/
gzip?: boolean;
/**
* CORS headers
* - false: No CORS headers (default)
* - true: Add permissive CORS headers for cross-origin access
*/
cors?: boolean;
/**
* Cache debugging
* - false: No cache headers (default)
* - true: Add X-From-Cache header when serving from cache
*/
cachedHeader?: boolean;Usage Examples:
// High-performance configuration
const fastHandler = st({
path: './assets',
gzip: true, // Compress responses
cachedHeader: true // Debug cache hits
});
// API-friendly configuration
const apiHandler = st({
path: './api-docs',
cors: true, // Allow cross-origin requests
gzip: true
});
// No-compression configuration (for pre-compressed files)
const preCompressedHandler = st({
path: './compressed-assets',
gzip: false // Files are already compressed
});Multi-level caching system configuration.
/**
* Cache configuration object or false to disable all caching
*/
cache?: CacheOptions | false;
interface CacheOptions {
/** File descriptor cache settings */
fd?: CacheConfig;
/** File stat cache settings */
stat?: CacheConfig;
/** File content cache settings */
content?: ContentCacheConfig;
/** Directory index HTML cache settings */
index?: CacheConfig;
/** Directory listing cache settings */
readdir?: CacheConfig;
}
interface CacheConfig {
/** Maximum number of items to cache */
max?: number;
/** Maximum age in milliseconds */
maxAge?: number;
/** Whether to ignore fetch abortion (default: true) */
ignoreFetchAbort?: boolean;
}
interface ContentCacheConfig extends CacheConfig {
/** Maximum memory size in bytes for content cache */
maxSize?: number;
/** Function to calculate item size (default: item.length) */
sizeCalculation?: (item: any) => number;
/** Custom Cache-Control header value */
cacheControl?: string;
}Default Cache Settings:
// Default cache configuration
const defaultCache = {
fd: {
max: 1000,
maxAge: 1000 * 60 * 60, // 1 hour
ignoreFetchAbort: true
},
stat: {
max: 5000,
maxAge: 1000 * 60, // 1 minute
ignoreFetchAbort: true
},
content: {
maxSize: 1024 * 1024 * 64, // 64MB
maxAge: 1000 * 60 * 10, // 10 minutes
ignoreFetchAbort: true
},
index: {
maxSize: 1024 * 8, // 8KB
maxAge: 1000 * 60 * 10, // 10 minutes
ignoreFetchAbort: true
},
readdir: {
maxSize: 1000,
maxAge: 1000 * 60 * 10, // 10 minutes
ignoreFetchAbort: true
}
};Usage Examples:
// Disable all caching
const noCacheHandler = st({
path: './dynamic',
cache: false
});
// Custom cache configuration
const customCacheHandler = st({
path: './static',
cache: {
content: {
maxSize: 1024 * 1024 * 256, // 256MB cache
maxAge: 1000 * 60 * 60, // 1 hour
cacheControl: 'public, max-age=3600'
},
stat: {
maxAge: 1000 * 30 // 30 second stat cache
}
}
});
// Memory-conscious configuration
const lightCacheHandler = st({
path: './files',
cache: {
content: {
maxSize: 1024 * 1024 * 16, // 16MB only
maxAge: 1000 * 60 * 5 // 5 minute cache
},
fd: {
max: 100 // Fewer file descriptors
}
}
});
// Development configuration with short cache times
const devCacheHandler = st({
path: './dev',
cache: {
content: {
maxAge: 1000 * 10, // 10 second cache
cacheControl: 'no-cache'
},
stat: {
maxAge: 1000 * 5 // 5 second stat cache
}
}
});Automatic cache control header management based on content cache configuration.
/**
* Cache-Control header behavior:
* - If content.maxAge is false: No Cache-Control header set
* - If content.cacheControl is string: Use that exact value
* - If cache is false: 'no-cache'
* - Default: 'public, max-age=' + (content.maxAge / 1000)
*/Usage Examples:
// Explicit cache control
const explicitHandler = st({
path: './assets',
cache: {
content: {
maxAge: 1000 * 60 * 60, // 1 hour
cacheControl: 'public, max-age=3600, immutable'
}
}
});
// No cache headers
const noCacheHeaderHandler = st({
path: './dynamic',
cache: {
content: {
maxAge: false // No Cache-Control header
}
}
});
// Private cache
const privateHandler = st({
path: './user-files',
cache: {
content: {
maxAge: 1000 * 60 * 10, // 10 minutes
cacheControl: 'private, max-age=600'
}
}
});Install with Tessl CLI
npx tessl i tessl/npm-st