Skip to content

Commit acb560d

Browse files
committed
feat(middleware): add basic auth and improve error handling 🔒
- Add BasicAuth middleware with user authentication - Add error handling documentation to context object - Add handleError method to Context class - Add MDN reference link to CORS documentation - Export BasicAuth in middleware index - Refactor CORS middleware to use handleError with try-catch - Refactor Handler to use ctx.handleError instead of handleResponse - Refactor WebSocket middleware to use handleError - Update documentation navigation and menu labels - Update README with Basic Auth middleware entry
1 parent ef190fa commit acb560d

15 files changed

Lines changed: 435 additions & 56 deletions

File tree

README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,11 @@ Follow our [installing guide](https://docs-deserve.neabyte.com/en/getting-starte
3030
- [Request Handling](https://docs-deserve.neabyte.com/en/core-concepts/request-handling) - Enhanced request object with automatic parsing
3131

3232
- **Middleware**
33-
- [Global Middleware](https://docs-deserve.neabyte.com/en/middleware/global) - Cross-cutting functionality
34-
- [Route-Specific Middleware](https://docs-deserve.neabyte.com/en/middleware/route-specific) - Targeted middleware for specific routes
35-
- [CORS Middleware](https://docs-deserve.neabyte.com/en/middleware/cors) - Cross-origin request handling
36-
- [WebSocket Middleware](https://docs-deserve.neabyte.com/en/middleware/websocket) - Real-time bidirectional communication
33+
- [Use Global](https://docs-deserve.neabyte.com/en/middleware/global) - Cross-cutting functionality
34+
- [Use Route-Specific](https://docs-deserve.neabyte.com/en/middleware/route-specific) - Targeted middleware for specific routes
35+
- [Basic Auth](https://docs-deserve.neabyte.com/en/middleware/basic-auth) - HTTP Basic Authentication
36+
- [CORS](https://docs-deserve.neabyte.com/en/middleware/cors) - Cross-origin request handling
37+
- [WebSocket](https://docs-deserve.neabyte.com/en/middleware/websocket) - Real-time bidirectional communication
3738

3839
- **Response Utilities**
3940
- [JSON Format](https://docs-deserve.neabyte.com/en/response/json) - Create JSON responses easily

docs/.vitepress/config.ts

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,11 @@ export default withMermaid(
9494
text: 'Middleware',
9595
collapsed: true,
9696
items: [
97-
{ text: 'Global Middleware', link: '/en/middleware/global' },
98-
{ text: 'Route-Specific Middleware', link: '/en/middleware/route-specific' },
99-
{ text: 'CORS Middleware', link: '/en/middleware/cors' },
100-
{ text: 'WebSocket Middleware', link: '/en/middleware/websocket' }
97+
{ text: 'Use Global', link: '/en/middleware/global' },
98+
{ text: 'Use Route-Specific', link: '/en/middleware/route-specific' },
99+
{ text: 'Basic Auth (Unreleased)', link: '/en/middleware/basic-auth' },
100+
{ text: 'CORS', link: '/en/middleware/cors' },
101+
{ text: 'WebSocket', link: '/en/middleware/websocket' }
101102
]
102103
},
103104
{
@@ -162,10 +163,11 @@ export default withMermaid(
162163
text: 'Middleware',
163164
collapsed: true,
164165
items: [
165-
{ text: 'Global Middleware', link: '/en/middleware/global' },
166-
{ text: 'Route-Specific Middleware', link: '/en/middleware/route-specific' },
167-
{ text: 'CORS Middleware', link: '/en/middleware/cors' },
168-
{ text: 'WebSocket Middleware', link: '/en/middleware/websocket' }
166+
{ text: 'Use Global', link: '/en/middleware/global' },
167+
{ text: 'Use Route-Specific', link: '/en/middleware/route-specific' },
168+
{ text: 'Basic Auth', link: '/en/middleware/basic-auth' },
169+
{ text: 'CORS', link: '/en/middleware/cors' },
170+
{ text: 'WebSocket', link: '/en/middleware/websocket' }
169171
]
170172
},
171173
{
@@ -270,10 +272,11 @@ export default withMermaid(
270272
text: 'Middleware',
271273
collapsed: true,
272274
items: [
273-
{ text: 'Middleware Global', link: '/id/middleware/global' },
274-
{ text: 'Middleware Spesifik Rute', link: '/id/middleware/route-specific' },
275-
{ text: 'Middleware CORS', link: '/id/middleware/cors' },
276-
{ text: 'Middleware WebSocket', link: '/id/middleware/websocket' }
275+
{ 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: 'CORS', link: '/id/middleware/cors' },
279+
{ text: 'WebSocket', link: '/id/middleware/websocket' }
277280
]
278281
},
279282
{

docs/en/core-concepts/context-object.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ Send responses using `ctx.send`:
7676
- `ctx.send.data()` - In-memory data downloads
7777
- `ctx.send.redirect()` - Redirects
7878
- `ctx.send.custom()` - Custom responses
79+
- `ctx.handleError()` - Error handling (unreleased)
7980

8081
You can also use `ctx.redirect()` directly as a convenience method:
8182

@@ -141,6 +142,47 @@ export function GET(ctx: Context): Response {
141142
}
142143
```
143144

145+
## Error Handling
146+
147+
> [!WARNING]
148+
> This feature is available in the development version but not yet released.
149+
150+
Handle errors consistently using `ctx.handleError()`:
151+
152+
```typescript
153+
export function GET(ctx: Context): Response {
154+
try {
155+
if (!isAuthorized) {
156+
return ctx.handleError(401, new Error('Unauthorized'))
157+
}
158+
return ctx.send.json({ data: 'success' })
159+
} catch (error) {
160+
return ctx.handleError(500, error as Error)
161+
}
162+
}
163+
```
164+
165+
### How It Works
166+
167+
`ctx.handleError()` respects your global error handler set with `router.catch()`:
168+
169+
- **If `router.catch()` is defined** - Uses your custom error handler
170+
- **If no error handler** - Returns a simple response with the status code
171+
172+
### Use in Middleware
173+
174+
Middleware can use `ctx.handleError()` to trigger error handling:
175+
176+
```typescript
177+
router.use(async (ctx, next) => {
178+
if (!isValid) {
179+
return ctx.handleError(401, new Error('Unauthorized'))
180+
// This will use router.catch() if defined
181+
}
182+
return await next()
183+
})
184+
```
185+
144186
## Context Lifecycle
145187

146188
1. **Request arrives** - Deserve creates Context with Request and URL

docs/en/middleware/basic-auth.md

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# Basic Auth Middleware
2+
3+
> **Reference**: [MDN HTTP Authentication Guide](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Authentication)
4+
5+
> [!WARNING]
6+
> This feature is available in the development version but not yet released.
7+
8+
HTTP Basic Authentication middleware for protecting routes with username and password authentication. Simple, secure, and easy to configure.
9+
10+
## Basic Usage
11+
12+
Protect routes with Basic Auth using `Mware.basicAuth()`:
13+
14+
```typescript
15+
import { Router, Mware } from '@neabyte/deserve'
16+
17+
const router = new Router()
18+
19+
router.use(
20+
Mware.basicAuth({
21+
users: [
22+
{ username: 'admin', password: 'secret' },
23+
{ username: 'user', password: 'pass' }
24+
]
25+
})
26+
)
27+
28+
router.serve(8000)
29+
```
30+
31+
## Route-Specific Protection
32+
33+
Apply Basic Auth only to specific routes:
34+
35+
```typescript
36+
// Protect only /api routes
37+
router.use(
38+
'/api',
39+
Mware.basicAuth({
40+
users: [{ username: 'admin', password: 'secret' }]
41+
})
42+
)
43+
44+
// Protect admin routes with different credentials
45+
router.use(
46+
'/admin',
47+
Mware.basicAuth({
48+
users: [{ username: 'admin', password: 'admin123' }]
49+
})
50+
)
51+
```
52+
53+
## Multiple Users
54+
55+
Support multiple user accounts:
56+
57+
```typescript
58+
router.use(
59+
Mware.basicAuth({
60+
users: [
61+
{ username: 'admin', password: 'admin123' },
62+
{ username: 'user', password: 'user123' },
63+
{ username: 'guest', password: 'guest123' }
64+
]
65+
})
66+
)
67+
```
68+
69+
## Error Handling
70+
71+
Basic Auth automatically uses `router.catch()` if defined:
72+
73+
```typescript
74+
router.catch((ctx, { statusCode, error }) => {
75+
if (statusCode === 401) {
76+
return ctx.send.json(
77+
{ error: 'Authentication required', message: error?.message ?? 'Unauthorized' },
78+
{ status: 401 }
79+
)
80+
}
81+
return ctx.send.json({
82+
error: error?.message ?? 'Unknown error'
83+
}, { status: statusCode })
84+
})
85+
86+
router.use(Mware.basicAuth({ users: [...] }))
87+
```
88+
89+
## Browser Authentication
90+
91+
Browsers will automatically prompt for credentials when accessing protected routes:
92+
93+
```
94+
Username: admin
95+
Password: ******
96+
```

docs/en/middleware/cors.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# CORS Middleware
22

3+
> **Reference**: [MDN HTTP CORS Guide](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CORS)
4+
35
CORS (Cross-Origin Resource Sharing) middleware handles cross-origin requests by adding appropriate headers and handling preflight OPTIONS requests.
46

57
## Basic Usage

docs/id/core-concepts/context-object.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ Kirim response menggunakan `ctx.send`:
7676
- `ctx.send.data()` - Unduhan data in-memory
7777
- `ctx.send.redirect()` - Redirect
7878
- `ctx.send.custom()` - Response custom
79+
- `ctx.handleError()` - Error handling (belum dirilis)
7980

8081
Anda juga dapat menggunakan `ctx.redirect()` secara langsung sebagai method convenience:
8182

@@ -141,6 +142,47 @@ export function GET(ctx: Context): Response {
141142
}
142143
```
143144

145+
## Penanganan Error
146+
147+
> [!WARNING]
148+
> Fitur ini tersedia di versi development tetapi belum dirilis.
149+
150+
Tangani error secara konsisten menggunakan `ctx.handleError()`:
151+
152+
```typescript
153+
export function GET(ctx: Context): Response {
154+
try {
155+
if (!isAuthorized) {
156+
return ctx.handleError(401, new Error('Unauthorized'))
157+
}
158+
return ctx.send.json({ data: 'success' })
159+
} catch (error) {
160+
return ctx.handleError(500, error as Error)
161+
}
162+
}
163+
```
164+
165+
### Cara Kerja
166+
167+
`ctx.handleError()` menghormati error handler global yang diatur dengan `router.catch()`:
168+
169+
- **Jika `router.catch()` didefinisikan** - Menggunakan error handler kustom Anda
170+
- **Jika tidak ada error handler** - Mengembalikan response sederhana dengan status code
171+
172+
### Gunakan di Middleware
173+
174+
Middleware dapat menggunakan `ctx.handleError()` untuk memicu error handling:
175+
176+
```typescript
177+
router.use(async (ctx, next) => {
178+
if (!isValid) {
179+
return ctx.handleError(401, new Error('Unauthorized'))
180+
// Ini akan menggunakan router.catch() jika didefinisikan
181+
}
182+
return await next()
183+
})
184+
```
185+
144186
## Lifecycle Context
145187

146188
1. **Request datang** - Deserve membuat Context dengan Request dan URL

docs/id/middleware/basic-auth.md

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# Middleware Basic Auth
2+
3+
> **Referensi**: [MDN HTTP Authentication Guide](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Authentication)
4+
5+
> [!WARNING]
6+
> Fitur ini tersedia di versi development tetapi belum dirilis.
7+
8+
Middleware HTTP Basic Authentication untuk melindungi route dengan autentikasi username dan password. Sederhana, aman, dan mudah dikonfigurasi.
9+
10+
## Penggunaan Dasar
11+
12+
Lindungi route dengan Basic Auth menggunakan `Mware.basicAuth()`:
13+
14+
```typescript
15+
import { Router, Mware } from '@neabyte/deserve'
16+
17+
const router = new Router()
18+
19+
router.use(
20+
Mware.basicAuth({
21+
users: [
22+
{ username: 'admin', password: 'secret' },
23+
{ username: 'user', password: 'pass' }
24+
]
25+
})
26+
)
27+
28+
router.serve(8000)
29+
```
30+
31+
## Proteksi Route-Spesifik
32+
33+
Terapkan Basic Auth hanya pada route tertentu:
34+
35+
```typescript
36+
// Lindungi hanya route /api
37+
router.use(
38+
'/api',
39+
Mware.basicAuth({
40+
users: [{ username: 'admin', password: 'secret' }]
41+
})
42+
)
43+
44+
// Lindungi route admin dengan kredensial berbeda
45+
router.use(
46+
'/admin',
47+
Mware.basicAuth({
48+
users: [{ username: 'admin', password: 'admin123' }]
49+
})
50+
)
51+
```
52+
53+
## Multiple Users
54+
55+
Mendukung beberapa akun pengguna:
56+
57+
```typescript
58+
router.use(
59+
Mware.basicAuth({
60+
users: [
61+
{ username: 'admin', password: 'admin123' },
62+
{ username: 'user', password: 'user123' },
63+
{ username: 'guest', password: 'guest123' }
64+
]
65+
})
66+
)
67+
```
68+
69+
## Penanganan Error
70+
71+
Basic Auth secara otomatis menggunakan `router.catch()` jika didefinisikan:
72+
73+
```typescript
74+
router.catch((ctx, { statusCode, error }) => {
75+
if (statusCode === 401) {
76+
return ctx.send.json(
77+
{ error: 'Autentikasi diperlukan', message: error?.message ?? 'Unauthorized' },
78+
{ status: 401 }
79+
)
80+
}
81+
return ctx.send.json({
82+
error: error?.message ?? 'Error tidak diketahui'
83+
}, { status: statusCode })
84+
})
85+
86+
router.use(Mware.basicAuth({ users: [...] }))
87+
```
88+
89+
## Autentikasi Browser
90+
91+
Browser akan secara otomatis meminta kredensial saat mengakses route yang dilindungi:
92+
93+
```
94+
Username: admin
95+
Password: ******
96+
```
97+

docs/id/middleware/cors.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Middleware CORS
22

3+
> **Referensi**: [MDN HTTP CORS Guide](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CORS)
4+
35
Middleware CORS (Cross-Origin Resource Sharing) menangani cross-origin requests dengan menambahkan header yang sesuai dan menangani preflight OPTIONS requests.
46

57
## Penggunaan Dasar

0 commit comments

Comments
 (0)