mirror of
https://github.com/oven-sh/bun
synced 2026-02-02 15:08:46 +00:00
Document static routes vs file routes in HTTP server (#21506)
## Summary - Add comprehensive documentation distinguishing static routes from file routes in `Bun.serve()` - Document caching behavior differences: ETag vs Last-Modified - Explain performance characteristics and error handling differences - Provide clear use case recommendations ## Changes - **File Responses vs Static Responses** section explaining the two approaches - **HTTP Caching Behavior** section detailing ETag and Last-Modified support - **Status Code Handling** section covering automatic 204/304 responses - Code examples showing both patterns with clear explanations ## Key Documentation Points - Static routes (`new Response(await file.bytes())`) buffer content in memory at startup - File routes (`new Response(Bun.file(path))`) read from filesystem per request - Static routes use ETags for caching, file routes use Last-Modified headers - File routes handle 404s automatically, static routes cause startup errors for missing files - Both support HTTP caching standards but with different validation strategies 🤖 Generated with [Claude Code](https://claude.ai/code) --------- Co-authored-by: Claude Bot <claude-bot@bun.sh> Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
@@ -164,6 +164,70 @@ Static responses do not allocate additional memory after initialization. You can
|
||||
|
||||
Static route responses are cached for the lifetime of the server object. To reload static routes, call `server.reload(options)`.
|
||||
|
||||
### File Responses vs Static Responses
|
||||
|
||||
When serving files in routes, there are two distinct behaviors depending on whether you buffer the file content or serve it directly:
|
||||
|
||||
```ts
|
||||
Bun.serve({
|
||||
routes: {
|
||||
// Static route - content is buffered in memory at startup
|
||||
"/logo.png": new Response(await Bun.file("./logo.png").bytes()),
|
||||
|
||||
// File route - content is read from filesystem on each request
|
||||
"/download.zip": new Response(Bun.file("./download.zip")),
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
**Static routes** (`new Response(await file.bytes())`) buffer content in memory at startup:
|
||||
|
||||
- **Zero filesystem I/O** during requests - content served entirely from memory
|
||||
- **ETag support** - Automatically generates and validates ETags for caching
|
||||
- **If-None-Match** - Returns `304 Not Modified` when client ETag matches
|
||||
- **No 404 handling** - Missing files cause startup errors, not runtime 404s
|
||||
- **Memory usage** - Full file content stored in RAM
|
||||
- **Best for**: Small static assets, API responses, frequently accessed files
|
||||
|
||||
**File routes** (`new Response(Bun.file(path))`) read from filesystem per request:
|
||||
|
||||
- **Filesystem reads** on each request - checks file existence and reads content
|
||||
- **Built-in 404 handling** - Returns `404 Not Found` if file doesn't exist or becomes inaccessible
|
||||
- **Last-Modified support** - Uses file modification time for `If-Modified-Since` headers
|
||||
- **If-Modified-Since** - Returns `304 Not Modified` when file hasn't changed since client's cached version
|
||||
- **Range request support** - Automatically handles partial content requests with `Content-Range` headers
|
||||
- **Streaming transfers** - Uses buffered reader with backpressure handling for efficient memory usage
|
||||
- **Memory efficient** - Only buffers small chunks during transfer, not entire file
|
||||
- **Best for**: Large files, dynamic content, user uploads, files that change frequently
|
||||
|
||||
### HTTP Caching Behavior
|
||||
|
||||
Both route types implement HTTP caching standards but with different strategies:
|
||||
|
||||
#### Static Routes Caching
|
||||
|
||||
- **ETag generation**: Automatically computes ETag hash from content at startup
|
||||
- **If-None-Match**: Validates client ETag against server ETag
|
||||
- **304 responses**: Returns `304 Not Modified` with empty body when ETags match
|
||||
- **Cache headers**: Inherits any `Cache-Control` headers you provide in the Response
|
||||
- **Consistency**: ETag remains constant until server restart or route reload
|
||||
|
||||
#### File Routes Caching
|
||||
|
||||
- **Last-Modified**: Uses file's `mtime` for `Last-Modified` header
|
||||
- **If-Modified-Since**: Compares client date with file modification time
|
||||
- **304 responses**: Returns `304 Not Modified` when file unchanged since client's cached version
|
||||
- **Content-Length**: Automatically set based on current file size
|
||||
- **Dynamic validation**: Checks file modification time on each request
|
||||
|
||||
#### Status Code Handling
|
||||
|
||||
Both route types automatically adjust status codes:
|
||||
|
||||
- **200 → 204**: Empty files (0 bytes) return `204 No Content` instead of `200 OK`
|
||||
- **200 → 304**: Successful cache validation returns `304 Not Modified`
|
||||
- **File routes only**: Missing or inaccessible files return `404 Not Found`
|
||||
|
||||
```ts
|
||||
const server = Bun.serve({
|
||||
static: {
|
||||
|
||||
Reference in New Issue
Block a user