Skip to content

Commit a4c8db8

Browse files
committed
feat(middleware): add body limit middleware ⚠️
- Add body limit documentation for English and Indonesian - Add BodyLimit middleware implementation - Export bodyLimit in middleware index - Fix Indonesian image path in index page - Fix Indonesian translation for route-specific middleware - Reorganize imports alphabetically in Handler.ts - Reorder warning blocks in basic-auth documentation - Update Basic Auth navigation labels with construction emoji - Update documentation navigation with body limit links - Update import paths from Types.ts to index.ts across source files - Update README with body limit middleware reference
1 parent acb560d commit a4c8db8

File tree

15 files changed

+301
-29
lines changed

15 files changed

+301
-29
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ Follow our [installing guide](https://docs-deserve.neabyte.com/en/getting-starte
3333
- [Use Global](https://docs-deserve.neabyte.com/en/middleware/global) - Cross-cutting functionality
3434
- [Use Route-Specific](https://docs-deserve.neabyte.com/en/middleware/route-specific) - Targeted middleware for specific routes
3535
- [Basic Auth](https://docs-deserve.neabyte.com/en/middleware/basic-auth) - HTTP Basic Authentication
36+
- [Body Limit](https://docs-deserve.neabyte.com/en/middleware/body-limit) - Enforce maximum request body size
3637
- [CORS](https://docs-deserve.neabyte.com/en/middleware/cors) - Cross-origin request handling
3738
- [WebSocket](https://docs-deserve.neabyte.com/en/middleware/websocket) - Real-time bidirectional communication
3839

docs/.vitepress/config.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,8 @@ export default withMermaid(
9696
items: [
9797
{ text: 'Use Global', link: '/en/middleware/global' },
9898
{ text: 'Use Route-Specific', link: '/en/middleware/route-specific' },
99-
{ text: 'Basic Auth (Unreleased)', link: '/en/middleware/basic-auth' },
99+
{ text: '🚧 Basic Auth', link: '/en/middleware/basic-auth' },
100+
{ text: '🚧 Body Limit', link: '/en/middleware/body-limit' },
100101
{ text: 'CORS', link: '/en/middleware/cors' },
101102
{ text: 'WebSocket', link: '/en/middleware/websocket' }
102103
]
@@ -165,7 +166,8 @@ export default withMermaid(
165166
items: [
166167
{ text: 'Use Global', link: '/en/middleware/global' },
167168
{ text: 'Use Route-Specific', link: '/en/middleware/route-specific' },
168-
{ text: 'Basic Auth', link: '/en/middleware/basic-auth' },
169+
{ text: '🚧 Basic Auth', link: '/en/middleware/basic-auth' },
170+
{ text: '🚧 Body Limit', link: '/en/middleware/body-limit' },
169171
{ text: 'CORS', link: '/en/middleware/cors' },
170172
{ text: 'WebSocket', link: '/en/middleware/websocket' }
171173
]
@@ -273,8 +275,9 @@ export default withMermaid(
273275
collapsed: true,
274276
items: [
275277
{ text: 'Gunakan Global', link: '/id/middleware/global' },
276-
{ text: 'Gunakan Route-Spesific', link: '/id/middleware/route-specific' },
277-
{ text: 'Basic Auth', link: '/id/middleware/basic-auth' },
278+
{ text: 'Gunakan Spesifik Rute', link: '/id/middleware/route-specific' },
279+
{ text: '🚧 Basic Auth', link: '/id/middleware/basic-auth' },
280+
{ text: '🚧 Body Limit', link: '/id/middleware/body-limit' },
278281
{ text: 'CORS', link: '/id/middleware/cors' },
279282
{ text: 'WebSocket', link: '/id/middleware/websocket' }
280283
]

docs/en/middleware/basic-auth.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
# Basic Auth Middleware
22

3-
> **Reference**: [MDN HTTP Authentication Guide](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Authentication)
3+
> [!WARNING] This feature is available in the development version but not yet released.
44
5-
> [!WARNING]
6-
> This feature is available in the development version but not yet released.
5+
> **Reference**: [MDN HTTP Authentication Guide](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Authentication)
76
87
HTTP Basic Authentication middleware for protecting routes with username and password authentication. Simple, secure, and easy to configure.
98

docs/en/middleware/body-limit.md

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
# Body Limit Middleware
2+
3+
> [!WARNING] This feature is available in the development version but not yet released.
4+
5+
> **Reference**: [RFC 7230 HTTP/1.1 Message Syntax and Routing](https://datatracker.ietf.org/doc/html/rfc7230#section-3.3.1)
6+
7+
Body Limit middleware enforces maximum request body size by checking the `Content-Length` header. Prevents large payloads from overwhelming your server.
8+
9+
## Basic Usage
10+
11+
Apply body limit middleware using Deserve's built-in middleware:
12+
13+
```typescript
14+
import { Router, Mware } from '@neabyte/deserve'
15+
16+
const router = new Router()
17+
18+
router.use(Mware.bodyLimit({
19+
limit: 1024 * 1024 // 1MB limit
20+
}))
21+
22+
await router.serve(8000)
23+
```
24+
25+
## Route-Specific Limits
26+
27+
Apply different body limits to specific routes:
28+
29+
```typescript
30+
// 1MB limit for general routes
31+
router.use(Mware.bodyLimit({ limit: 1024 * 1024 }))
32+
33+
// 5MB limit for upload routes
34+
router.use('/uploads', Mware.bodyLimit({ limit: 5 * 1024 * 1024 }))
35+
36+
// 10MB limit for API routes
37+
router.use('/api', Mware.bodyLimit({ limit: 10 * 1024 * 1024 }))
38+
```
39+
40+
## Configuration Options
41+
42+
### `limit`
43+
44+
Maximum body size in bytes:
45+
46+
```typescript
47+
// 1MB (1,048,576 bytes)
48+
limit: 1024 * 1024
49+
50+
// 5MB (5,242,880 bytes)
51+
limit: 5 * 1024 * 1024
52+
53+
// 10MB (10,485,760 bytes)
54+
limit: 10 * 1024 * 1024
55+
```
56+
57+
## How It Works
58+
59+
The middleware checks the `Content-Length` header before the body is read:
60+
61+
1. **GET/HEAD requests** - Automatically skipped (no body)
62+
2. **Content-Length present** - Validates against limit
63+
3. **Transfer-Encoding present** - Passes through (chunked encoding)
64+
4. **No headers** - Passes through (size unknown)
65+
66+
### RFC 7230 Compliance
67+
68+
The middleware follows RFC 7230:
69+
- If both `Transfer-Encoding` and `Content-Length` are present, `Transfer-Encoding` takes precedence and body size is not validated
70+
- Only validates `Content-Length` when `Transfer-Encoding` is absent
71+
- Handles chunked encoding by passing through (can't check size upfront)
72+
73+
## Complete Example
74+
75+
```typescript
76+
import { Router, Mware } from '@neabyte/deserve'
77+
78+
const router = new Router({ routesDir: './routes' })
79+
80+
// Global 1MB limit
81+
router.use(Mware.bodyLimit({ limit: 1024 * 1024 }))
82+
83+
// 5MB for file uploads
84+
router.use('/uploads', Mware.bodyLimit({ limit: 5 * 1024 * 1024 }))
85+
86+
// 10MB for API routes
87+
router.use('/api', Mware.bodyLimit({ limit: 10 * 1024 * 1024 }))
88+
89+
await router.serve(8000)
90+
```
91+
92+
## Error Handling
93+
94+
Body Limit automatically uses `router.catch()` if defined:
95+
96+
```typescript
97+
router.catch((ctx, { statusCode, error }) => {
98+
if (statusCode === 413) {
99+
return ctx.send.json(
100+
{ error: 'Request entity too large', message: error?.message },
101+
{ status: 413 }
102+
)
103+
}
104+
return ctx.send.json({
105+
error: error?.message ?? 'Unknown error'
106+
}, { status: statusCode })
107+
})
108+
109+
router.use(Mware.bodyLimit({ limit: 1024 * 1024 }))
110+
```
111+
112+
When the limit is exceeded, the middleware returns message `Request entity too large` with `status code: 413` before the request body is read.

docs/id/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ hero:
66
text: "Framework Web"
77
tagline: "Bangun server HTTP dengan mudah tanpa konfigurasi untuk produktivitas."
88
image:
9-
src: /public/image.png
9+
src: /image.png
1010
alt: Deserve
1111

1212
actions:

docs/id/middleware/basic-auth.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
# Middleware Basic Auth
22

3-
> **Referensi**: [MDN HTTP Authentication Guide](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Authentication)
3+
> [!WARNING] Fitur ini tersedia di versi development tetapi belum dirilis.
44
5-
> [!WARNING]
6-
> Fitur ini tersedia di versi development tetapi belum dirilis.
5+
> **Referensi**: [MDN HTTP Authentication Guide](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Authentication)
76
87
Middleware HTTP Basic Authentication untuk melindungi route dengan autentikasi username dan password. Sederhana, aman, dan mudah dikonfigurasi.
98

docs/id/middleware/body-limit.md

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
# Middleware Body Limit
2+
3+
> [!WARNING] Fitur ini tersedia di versi development tetapi belum dirilis.
4+
5+
> **Referensi**: [RFC 7230 HTTP/1.1 Message Syntax and Routing](https://datatracker.ietf.org/doc/html/rfc7230#section-3.3.1)
6+
7+
Middleware Body Limit menegakkan ukuran body request maksimum dengan memeriksa header `Content-Length`. Mencegah payload besar yang dapat membebani server Anda.
8+
9+
## Penggunaan Dasar
10+
11+
Terapkan middleware body limit menggunakan middleware built-in Deserve:
12+
13+
```typescript
14+
import { Router, Mware } from '@neabyte/deserve'
15+
16+
const router = new Router()
17+
18+
router.use(Mware.bodyLimit({
19+
limit: 1024 * 1024 // 1MB limit
20+
}))
21+
22+
await router.serve(8000)
23+
```
24+
25+
## Limit Spesifik Rute
26+
27+
Terapkan limit body berbeda pada route tertentu:
28+
29+
```typescript
30+
// Limit 1MB untuk route umum
31+
router.use(Mware.bodyLimit({ limit: 1024 * 1024 }))
32+
33+
// Limit 5MB untuk route upload
34+
router.use('/uploads', Mware.bodyLimit({ limit: 5 * 1024 * 1024 }))
35+
36+
// Limit 10MB untuk route API
37+
router.use('/api', Mware.bodyLimit({ limit: 10 * 1024 * 1024 }))
38+
```
39+
40+
## Opsi Konfigurasi
41+
42+
### `limit`
43+
44+
Ukuran body maksimum dalam bytes:
45+
46+
```typescript
47+
// 1MB (1,048,576 bytes)
48+
limit: 1024 * 1024
49+
50+
// 5MB (5,242,880 bytes)
51+
limit: 5 * 1024 * 1024
52+
53+
// 10MB (10,485,760 bytes)
54+
limit: 10 * 1024 * 1024
55+
```
56+
57+
## Cara Kerja
58+
59+
Middleware memeriksa header `Content-Length` sebelum body dibaca:
60+
61+
1. **Request GET/HEAD** - Secara otomatis dilewati (tidak ada body)
62+
2. **Content-Length ada** - Memvalidasi terhadap limit
63+
3. **Transfer-Encoding ada** - Melewati (chunked encoding)
64+
4. **Tidak ada header** - Melewati (ukuran tidak diketahui)
65+
66+
### Kepatuhan RFC 7230
67+
68+
Middleware mengikuti RFC 7230:
69+
- Jika `Transfer-Encoding` dan `Content-Length` keduanya ada, `Transfer-Encoding` memiliki prioritas dan ukuran body tidak divalidasi
70+
- Hanya memvalidasi `Content-Length` ketika `Transfer-Encoding` tidak ada
71+
- Menangani chunked encoding dengan melewati (tidak dapat memeriksa ukuran sebelumnya)
72+
73+
## Contoh Lengkap
74+
75+
```typescript
76+
import { Router, Mware } from '@neabyte/deserve'
77+
78+
const router = new Router({ routesDir: './routes' })
79+
80+
// Limit global 1MB
81+
router.use(Mware.bodyLimit({ limit: 1024 * 1024 }))
82+
83+
// 5MB untuk upload file
84+
router.use('/uploads', Mware.bodyLimit({ limit: 5 * 1024 * 1024 }))
85+
86+
// 10MB untuk route API
87+
router.use('/api', Mware.bodyLimit({ limit: 10 * 1024 * 1024 }))
88+
89+
await router.serve(8000)
90+
```
91+
92+
## Penanganan Error
93+
94+
Body Limit secara otomatis menggunakan `router.catch()` jika didefinisikan:
95+
96+
```typescript
97+
router.catch((ctx, { statusCode, error }) => {
98+
if (statusCode === 413) {
99+
return ctx.send.json(
100+
{ error: 'Request entity too large', message: error?.message },
101+
{ status: 413 }
102+
)
103+
}
104+
return ctx.send.json({
105+
error: error?.message ?? 'Error tidak diketahui'
106+
}, { status: statusCode })
107+
})
108+
109+
router.use(Mware.bodyLimit({ limit: 1024 * 1024 }))
110+
```
111+
112+
Ketika limit terlampaui, middleware mengembalikan pesan `Request entity too large` dengan `status code: 413` sebelum body request dibaca.

src/Context.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { ErrorHandler } from '@app/Types.ts'
1+
import type { ErrorHandler } from '@app/index.ts'
22

33
/**
44
* Request context class.

src/Handler.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1-
import type {
2-
ErrorMiddleware,
3-
Middleware,
4-
MiddlewareEntry,
5-
RouteHandler,
6-
RouteMetadata,
7-
ServeOptions,
8-
StaticFileHandler
9-
} from '@app/Types.ts'
10-
import { FastRouter } from '@neabyte/fast-router'
1+
import {
2+
Context,
3+
type ErrorMiddleware,
4+
type Middleware,
5+
type MiddlewareEntry,
6+
type RouteHandler,
7+
type RouteMetadata,
8+
type ServeOptions,
9+
type StaticFileHandler
10+
} from '@app/index.ts'
1111
import { pathToFileURL } from 'node:url'
12+
import { FastRouter } from '@neabyte/fast-router'
1213
import { allowedExtensions, contentTypes, httpMethods } from '@app/Constant.ts'
13-
import { Context } from '@app/Context.ts'
1414

1515
/**
1616
* Request handler class.

src/Router.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { ErrorMiddleware, Middleware, RouterOptions, ServeOptions } from '@app/Types.ts'
1+
import type { ErrorMiddleware, Middleware, RouterOptions, ServeOptions } from '@app/index.ts'
22
import { Handler } from '@app/Handler.ts'
33

44
/**

0 commit comments

Comments
 (0)