Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ lib
dist

.DS_Store
test_static_files/
3 changes: 2 additions & 1 deletion biome.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
"noExplicitAny": "off"
},
"style": {
"useTemplate": "off"
"useTemplate": "off",
"useNodejsImportProtocol": "error"
}
}
},
Expand Down
44 changes: 44 additions & 0 deletions packages/wobe-documentation/doc/ecosystem/hooks/html.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# html (static files)

`html` serves static files (HTML, JS, CSS, images, etc.) from a directory with guardrails similar to `express.static`: traversal blocking, dotfiles ignored by default, symlink checks, and SPA fallback support.

## Quick usage

```ts
import { Wobe, html } from 'wobe'
import { join } from 'node:path'

const staticRoot = join(__dirname, '../fixtures')

new Wobe()
// Serve under /tata while stripping that prefix for file resolution
.get(
'/tata/*',
html({
rootPath: staticRoot,
fallbackFile: 'index.html', // optional for SPA
stripPrefix: '/tata',
})
)
.listen(3000)

// http://localhost:3000/tata/test.html -> serves fixtures/test.html
// http://localhost:3000/tata/unknown -> serves fixtures/index.html (fallback)
```

## Options

- `rootPath` (string, required): root directory of static files.
- `fallbackFile` (string, optional): file served on 404, useful for SPAs (`text/html`).
- `stripPrefix` (string, optional): prefix to strip from the pathname when mounted under a sub-path (e.g. `/static` or `/tata`).
- `allowDotfiles` (boolean, default `false`): serve dotfiles; otherwise they return 404.
- `allowSymlinks` (boolean, default `false`): allow symlinks pointing outside `rootPath`; otherwise realpath must stay inside root or 403.

## Behavior and safety

- **Methods**: only `GET` and `HEAD` are accepted (`405` otherwise). HEAD returns headers only.
- **Dotfiles**: ignored by default (404).
- **Traversal / symlinks**: path is normalized + realpathed and must stay under `rootPath` unless `allowSymlinks` is true; otherwise 403.
- **Content-Type**: inferred from extension (built-in MIME table); text read via `.text()`, binary via `arrayBuffer()`.
- **SPA fallback**: served only if it resolves inside root (same symlink rule); otherwise 403.
- **Mounted prefixes**: use `stripPrefix` to exclude the mount prefix from file resolution.
6 changes: 5 additions & 1 deletion packages/wobe-documentation/doc/ecosystem/hooks/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,12 @@ export const authorizationHook = (schema: TSchema): WobeHandler => {
throw new HttpException(
new Response('You are not authorized to access to this route', {
status: 403,
}),
})
)
}
}
```

## Available hooks

- [html](./html.md) — serve static files with SPA fallback, traversal/dotfile guards, GET/HEAD only.
18 changes: 14 additions & 4 deletions packages/wobe/dev/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
process.env.NODE_TEST = 'test'
import { join } from 'node:path'
import { Wobe, uploadDirectory } from '../src'
import { Wobe, uploadDirectory, html } from '../src'

const staticRoot = join(__dirname, '../fixtures')

new Wobe()
.get('/', (ctx) => ctx.res.send('Hi'))
// Sample API route
.get('/api', (ctx) => ctx.res.send('Hi'))
// Example of using the uploadDirectory hook
.get('/bucket/:filename', uploadDirectory({ directory: staticRoot }))
// Serve static assets and fallback to testFile.html for SPA-style routing
.get(
'/bucket/:filename',
uploadDirectory({ directory: join(__dirname, '../fixtures') }),
'/tata/*',
html({
rootPath: staticRoot,
fallbackFile: 'testFile.html',
stripPrefix: '/tata',
}),
)
.listen(3000)
5 changes: 5 additions & 0 deletions packages/wobe/fixtures/test.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<html>
<body>
<h1>Hello World</h1>
</body>
</html>
Loading