Skip to content

Commit b4405d0

Browse files
committed
feat(docs): document byte-range static responses
- Add a byte-range section covering 206, 416, and full-file fallback - Reword the .env rejection example to match the updated diagram
1 parent 4648a0c commit b4405d0

2 files changed

Lines changed: 26 additions & 6 deletions

File tree

docs/id/static-file/basic.md

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Sajikan file statis (HTML, CSS, JS, images) menggunakan method `static()`.
1010

1111
Sajikan file statis dari direktori:
1212

13-
![Memanggil router.static dengan prefix garis miring static dan path titik garis miring public mendaftarkan pola garis miring static garis miring bintang bintang, lalu tiap request prefix garis miring static-nya dipotong dari ctx.pathname dan sisanya digabung di bawah public, jadi garis miring static memetakan ke public garis miring index titik html, garis miring static garis miring css garis miring style titik css memetakan ke public garis miring css garis miring style titik css, dan segmen apa pun yang diawali titik atau titik titik atau path yang lolos dari base ditolak dengan 404 sebelum pembacaan apa pun](/diagrams/static-url-to-file.png)
13+
![Memanggil router.static dengan prefix garis miring static dan path titik garis miring public mendaftarkan pola garis miring static garis miring bintang bintang, lalu tiap request prefix garis miring static-nya dipotong dari ctx.pathname dan sisanya digabung di bawah public, jadi garis miring static memetakan ke public garis miring index titik html, garis miring static garis miring css garis miring style titik css memetakan ke public garis miring css garis miring style titik css, dan garis miring static garis miring titik env ditolak dengan 404 sebelum pembacaan apa pun karena segmennya diawali titik](/diagrams/static-url-to-file.png)
1414

1515
```typescript twoslash
1616
import { Router } from '@neabyte/deserve'
@@ -31,7 +31,7 @@ Ini menyajikan file dari direktori `public/` di path URL `/static`:
3131

3232
- `GET /static/index.html` → menyajikan `public/index.html`
3333
- `GET /static/css/style.css` → menyajikan `public/css/style.css`
34-
- `GET /static/js/app.js`menyajikan `public/js/app.js`
34+
- `GET /static/.env`ditolak dengan **404** sebelum pembacaan apa pun
3535

3636

3737
## Cara Kerja
@@ -81,7 +81,7 @@ router.static('/assets', {
8181

8282
### `etag`
8383

84-
Aktifkan generasi ETag untuk caching. Tag adalah hash SHA-256 dari ukuran file dan waktu modifikasi, bukan isi file penuh, jadi tetap murah dihitung:
84+
Aktifkan pembuatan ETag untuk caching. Tag adalah hash SHA-256 dari ukuran file dan waktu modifikasi, bukan isi file penuh, jadi tetap murah dihitung:
8585

8686
```typescript twoslash
8787
import { Router } from '@neabyte/deserve'
@@ -116,12 +116,22 @@ router.static('/assets', {
116116
})
117117
```
118118

119+
## Permintaan Byte-Range
120+
121+
Response statis mendukung satu [byte range](https://www.rfc-editor.org/rfc/rfc7233) sehingga klien bisa mengambil sebagian berkas, yang diandalkan oleh penggeser video atau unduhan yang bisa dilanjutkan. Setiap response statis mengumumkan `Accept-Ranges: bytes`, dan request yang membawa satu header `Range` kontigu dijawab dengan jendela yang cocok:
122+
123+
- **Satu range valid** mengembalikan **206 Partial Content** dengan header `Content-Range: bytes start-end/size` dan hanya byte itu yang dialirkan dari disk.
124+
- **Range tak terpenuhi** yang menyebut jendela melewati ukuran berkas mengembalikan **416 Range Not Satisfiable** dengan `Content-Range: bytes */size`.
125+
- **Range yang tidak ada, multi-bagian, atau tidak valid** kembali menyajikan berkas penuh seperti sebelumnya.
126+
127+
Hanya byte di dalam jendela yang diminta yang dibaca, dan handle berkas dilepas begitu jendela terkirim, error, atau dibatalkan.
128+
119129
## Resolusi File dan Keamanan
120130

121131
Penyajian static memetakan path URL ke file di bawah direktori yang dikonfigurasi, dengan beberapa aturan bawaan:
122132

123133
- **Index fallback** - request ke root route menyajikan `index.html` dari direktori.
124-
- **Content type** - tipe dipilih dari ekstensi file. Aset web umum seperti HTML, CSS, JavaScript, JSON, images, fonts, dan dokumen sudah dipetakan langsung, dan ekstensi tidak dikenal jatuh ke `application/octet-stream`.
134+
- **Content type** - tipe dipilih dari ekstensi file. Aset web umum seperti HTML, CSS, JavaScript, JSON, images, fonts, dan dokumen sudah dipetakan langsung, dan ekstensi tidak dikenal memakai `application/octet-stream`.
125135
- **Dotfiles diblokir** - segment path apa pun yang namanya diawali `.` ditolak dengan **404**, jadi file seperti `.env`, `.git/config`, atau `..` di awal tidak pernah disajikan. Aturan melihat nama segment, bukan ekstensi, jadi file biasa seperti `report.env` tetap disajikan.
126136
- **Directory traversal diblokir** - real path hasil resolusi harus tetap di dalam direktori dasar. Path yang lolos keluar, misalnya dibangun dari `..`, ditolak dengan **404**.
127137

docs/static-file/basic.md

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Serve static files (HTML, CSS, JS, images) using the `static()` method.
1010

1111
Serve static files from a directory:
1212

13-
![Calling router.static with the prefix slash static and path dot slash public registers the pattern slash static slash star star, then each request has its slash static prefix sliced off ctx.pathname and the remainder joined under public, so slash static maps to public slash index dot html, slash static slash css slash style dot css maps to public slash css slash style dot css, and any segment starting with a dot or dot dot or a path escaping the base is rejected with 404 before any read](/diagrams/static-url-to-file.png)
13+
![Calling router.static with the prefix slash static and path dot slash public registers the pattern slash static slash star star, then each request has its slash static prefix sliced off ctx.pathname and the remainder joined under public, so slash static maps to public slash index dot html, slash static slash css slash style dot css maps to public slash css slash style dot css, and slash static slash dot env is rejected with 404 before any read because the segment starts with a dot](/diagrams/static-url-to-file.png)
1414

1515
```typescript twoslash
1616
import { Router } from '@neabyte/deserve'
@@ -31,7 +31,7 @@ This serves files from the `public/` directory at the `/static` URL path:
3131

3232
- `GET /static/index.html` → serves `public/index.html`
3333
- `GET /static/css/style.css` → serves `public/css/style.css`
34-
- `GET /static/js/app.js`serves `public/js/app.js`
34+
- `GET /static/.env`rejected with **404** before any read
3535

3636

3737
## How It Works
@@ -116,6 +116,16 @@ router.static('/assets', {
116116
})
117117
```
118118

119+
## Byte-Range Requests
120+
121+
Static responses support a single [byte range](https://www.rfc-editor.org/rfc/rfc7233) so a client can fetch part of a file, which is what a video scrubber or a resumable download relies on. Every static response advertises `Accept-Ranges: bytes`, and a request carrying one contiguous `Range` header is answered with the matched window:
122+
123+
- **One valid range** returns **206 Partial Content** with a `Content-Range: bytes start-end/size` header and only those bytes streamed off disk.
124+
- **An unsatisfiable range** that names a window past the file size returns **416 Range Not Satisfiable** with `Content-Range: bytes */size`.
125+
- **An absent, multi-part, or malformed range** falls back to the full file as before.
126+
127+
Only the bytes inside the requested window are read, and the file handle is released once the window is sent, errors, or is cancelled.
128+
119129
## File Resolution and Security
120130

121131
Static serving maps a URL path to a file under the configured directory, with a few built-in rules:

0 commit comments

Comments
 (0)