Static Files
Serve static files (HTML, CSS, JavaScript, images, etc.) with built-in security.
Installation
dart pub add aim_server_staticQuick Start
import 'dart:io';
import 'package:aim_server/aim_server.dart';
import 'package:aim_server_static/aim_server_static.dart';
void main() async {
final app = Aim();
// Serve files from 'public' directory
app.use(serveStatic('public'));
await app.serve(host: InternetAddress.anyIPv4, port: 8080);
}Directory structure:
public/
├── index.html
├── styles.css
├── script.js
└── images/
└── logo.pngAccess files:
http://localhost:8080/index.htmlhttp://localhost:8080/styles.csshttp://localhost:8080/images/logo.png
Configuration
Custom Root Directory
app.use(serveStatic('assets'));
app.use(serveStatic('dist'));Path Prefix
Serve static files under a specific path:
app.use(serveStatic(
'public',
path: '/static',
));Access: http://localhost:8080/static/index.html
Index Files
Automatically serve index files:
app.use(serveStatic(
'public',
index: 'index.html', // Default
));Request to / serves /index.html
Complete Example
import 'dart:io';
import 'package:aim_server/aim_server.dart';
import 'package:aim_server_static/aim_server_static.dart';
void main() async {
final app = Aim();
// Serve static files
app.use(serveStatic(
'public',
index: 'index.html',
));
// API routes
app.get('/api/data', (c) async {
return c.json({'message': 'API response'});
});
// Fallback for SPA (Single Page Application)
app.notFound((c) async {
final indexFile = File('public/index.html');
if (await indexFile.exists()) {
final content = await indexFile.readAsString();
return c.html(content);
}
return c.json({'error': 'Not Found'}, statusCode: 404);
});
await app.serve(host: InternetAddress.anyIPv4, port: 8080);
print('Server running on http://localhost:8080');
}MIME Types
The middleware automatically sets correct Content-Type headers:
| Extension | MIME Type |
|---|---|
.html | text/html |
.css | text/css |
.js | application/javascript |
.json | application/json |
.png | image/png |
.jpg, .jpeg | image/jpeg |
.gif | image/gif |
.svg | image/svg+xml |
.pdf | application/pdf |
.txt | text/plain |
Security Features
The middleware includes built-in security:
- Path traversal prevention - Blocks
../attempts - Hidden file protection - Blocks files starting with
. - Safe path resolution - Validates all paths
Directory Listing
WARNING
Directory listing is disabled by default for security. Files must be accessed by exact path.
SPA Support
For Single Page Applications (React, Vue, etc.):
import 'dart:io';
import 'package:aim_server/aim_server.dart';
import 'package:aim_server_static/aim_server_static.dart';
void main() async {
final app = Aim();
// Serve static assets
app.use(serveStatic('dist'));
// API routes
app.get('/api/*', apiHandler);
// SPA fallback - serve index.html for unmatched routes
app.notFound((c) async {
final indexFile = File('dist/index.html');
final content = await indexFile.readAsString();
return c.html(content);
});
await app.serve(host: InternetAddress.anyIPv4, port: 8080);
}Multiple Static Directories
// Serve from multiple directories
app.use(serveStatic('public'));
app.use(serveStatic('assets', path: '/assets'));
app.use(serveStatic('uploads', path: '/uploads'));Caching
Add cache headers for performance:
app.use((c, next) async {
if (c.req.path.startsWith('/static/')) {
c.header('Cache-Control', 'public, max-age=31536000'); // 1 year
}
return next();
});
app.use(serveStatic('public', path: '/static'));Example Project Structure
my_app/
├── bin/
│ └── server.dart
├── public/
│ ├── index.html
│ ├── css/
│ │ └── style.css
│ ├── js/
│ │ └── app.js
│ └── images/
│ └── logo.png
└── pubspec.yamlpublic/index.html:
<!DOCTYPE html>
<html>
<head>
<title>My App</title>
<link rel="stylesheet" href="/css/style.css">
</head>
<body>
<h1>Welcome</h1>
<img src="/images/logo.png" alt="Logo">
<script src="/js/app.js"></script>
</body>
</html>Best Practices
Separate static and dynamic routes
dartapp.use(serveStatic('public', path: '/static')); app.get('/api/*', apiHandler);Use versioned assets
html<link rel="stylesheet" href="/css/style.v1.2.3.css">Set cache headers
dartc.header('Cache-Control', 'public, max-age=31536000');Compress assets (gzip, brotli) before serving
Use CDN for production - Consider CloudFlare, AWS CloudFront
Testing
# Serve files
curl http://localhost:8080/index.html
# With prefix
curl http://localhost:8080/static/style.css
# Check MIME type
curl -I http://localhost:8080/logo.pngSecurity Considerations
Never serve source code
dart// Don't serve from project root app.use(serveStatic('.')); // ❌ Bad // Serve from specific directory app.use(serveStatic('public')); // ✅ GoodBlock sensitive files
.envfiles- Configuration files
- Database files
- Source code
Use HTTPS in production
Set security headers
dartc.header('X-Content-Type-Options', 'nosniff'); c.header('X-Frame-Options', 'DENY');
Next Steps
- Learn about Multipart for file uploads
- Explore CORS for cross-origin requests
- Read about Security best practices
