feat: resolve request paths within contained site roots
This commit is contained in:
parent
6a3a198975
commit
3031b8acdd
9 changed files with 1257 additions and 8 deletions
31
README.md
31
README.md
|
|
@ -8,12 +8,13 @@ A Rust re-implementation of [smolweb](https://code.randogoth.com/randogoth/smolw
|
|||
|
||||
## Status
|
||||
|
||||
Early. The configuration layer is implemented and tested; nothing is served yet.
|
||||
Early. Configuration and path resolution are implemented and tested; nothing is served yet.
|
||||
|
||||
| Area | State |
|
||||
| --- | --- |
|
||||
| Server configuration, virtual hosts, `--check` | implemented |
|
||||
| Path resolution and the render cache | planned |
|
||||
| Path resolution, traversal containment, live reload | implemented |
|
||||
| Markdown parsing | planned |
|
||||
| gemtext and HTML output | planned |
|
||||
| HTTP, Spartan and Nex listeners | planned |
|
||||
| 80-column text and Nex output | planned |
|
||||
|
|
@ -40,6 +41,19 @@ default_site = "smol"
|
|||
|
||||
A `.itsybitsy.toml` in any content directory says how the Markdown in **that directory** renders. There is no inheritance: a subdirectory without its own file uses the built-in defaults rather than its parent's. Repetition in a deep tree is the price of never having to look elsewhere to know how a page renders.
|
||||
|
||||
```toml
|
||||
[defaults]
|
||||
cache_control = 3600
|
||||
|
||||
[page."index.md"]
|
||||
title = "Notes"
|
||||
cache_control = 300
|
||||
```
|
||||
|
||||
`[defaults]` applies to every Markdown file in the directory; a `[page."name.md"]` table overrides it for one file. `title` is per-page by nature, so setting it in `[defaults]` is an error; left unset, it is derived from the page's first level-1 heading. Each renderer's own keys arrive with that renderer. Editing the file re-renders that directory's pages on the next request, and a file that fails to parse makes them error rather than silently falling back to defaults.
|
||||
|
||||
Because the name begins with a dot, the same rule that keeps `.secret.md` out of the URL space keeps this file out of it too.
|
||||
|
||||
`--check` validates the configuration and reports the routing it resolved, without binding a port:
|
||||
|
||||
```console
|
||||
|
|
@ -56,6 +70,19 @@ formats rendered per page: html, xhtmlmp
|
|||
|
||||
Everything the schema cannot express is checked here rather than on first request: a format no enabled feature provides, two sites claiming one hostname, a content root that does not exist, a server file sitting inside a content root where it would be served.
|
||||
|
||||
## URLs
|
||||
|
||||
Links should be root-relative and extensionless (`[about](/about)`, not `about.md`), so the same link resolves identically from every protocol.
|
||||
|
||||
| Request | Serves |
|
||||
| --- | --- |
|
||||
| `/` | `index.md` |
|
||||
| `/foo` | `foo.md`, else `foo/index.md` |
|
||||
| `/foo.md` | redirects to `/foo` |
|
||||
| `/img.png` | the file itself, by media type |
|
||||
|
||||
Nothing outside the content root is reachable. A request target is percent-decoded before it is normalised, so an encoded `..` becomes a real one and gets clamped at the root rather than quietly matching nothing; any path component beginning with a dot is refused outright; and whatever survives is canonicalised and required to still be inside the root, which is what defeats a symlink pointing out of it. There are no generated directory listings — only `index.md`.
|
||||
|
||||
## Development
|
||||
|
||||
```bash
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue