balda-js 0.0.1 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -6
- package/.husky/pre-commit +0 -19
- package/.nvmrc +0 -1
- package/docs/README.md +0 -135
- package/docs/blog/authors.yml +0 -6
- package/docs/blog/tags.yml +0 -4
- package/docs/cli.md +0 -109
- package/docs/docs/core-concepts/controllers.md +0 -393
- package/docs/docs/core-concepts/middleware.md +0 -302
- package/docs/docs/core-concepts/request-response.md +0 -486
- package/docs/docs/core-concepts/routing.md +0 -388
- package/docs/docs/core-concepts/server.md +0 -332
- package/docs/docs/cron/overview.md +0 -70
- package/docs/docs/examples/rest-api.md +0 -595
- package/docs/docs/getting-started/configuration.md +0 -168
- package/docs/docs/getting-started/installation.md +0 -125
- package/docs/docs/getting-started/quick-start.md +0 -273
- package/docs/docs/intro.md +0 -46
- package/docs/docs/plugins/cookie.md +0 -424
- package/docs/docs/plugins/cors.md +0 -295
- package/docs/docs/plugins/file.md +0 -382
- package/docs/docs/plugins/helmet.md +0 -388
- package/docs/docs/plugins/json.md +0 -338
- package/docs/docs/plugins/log.md +0 -592
- package/docs/docs/plugins/overview.md +0 -390
- package/docs/docs/plugins/rate-limiter.md +0 -347
- package/docs/docs/plugins/static.md +0 -352
- package/docs/docs/plugins/swagger.md +0 -411
- package/docs/docs/plugins/urlencoded.md +0 -76
- package/docs/docs/testing/examples.md +0 -384
- package/docs/docs/testing/mock-server.md +0 -311
- package/docs/docs/testing/overview.md +0 -76
- package/docs/docusaurus.config.ts +0 -144
- package/docs/intro.md +0 -78
- package/docs/package.json +0 -46
- package/docs/sidebars.ts +0 -72
- package/docs/static/.nojekyll +0 -0
- package/docs/static/img/docusaurus-social-card.jpg +0 -0
- package/docs/static/img/docusaurus.png +0 -0
- package/docs/static/img/favicon.ico +0 -0
- package/docs/static/img/logo.svg +0 -1
- package/docs/static/img/undraw_docusaurus_mountain.svg +0 -37
- package/docs/static/img/undraw_docusaurus_react.svg +0 -170
- package/docs/static/img/undraw_docusaurus_tree.svg +0 -40
- package/docs/tsconfig.json +0 -8
- package/speed_test.sh +0 -3
- package/test/benchmark/index.ts +0 -17
- package/test/cli/cli.ts +0 -7
- package/test/commands/test.ts +0 -42
- package/test/controllers/file_upload.ts +0 -29
- package/test/controllers/urlencoded.ts +0 -13
- package/test/controllers/users.ts +0 -111
- package/test/cron/index.ts +0 -6
- package/test/cron/test_cron.ts +0 -8
- package/test/cron/test_cron_imported.ts +0 -8
- package/test/native_env.ts +0 -16
- package/test/resources/test.txt +0 -1
- package/test/server/index.ts +0 -3
- package/test/server/instance.ts +0 -63
- package/test/suite/upload.test.ts +0 -23
- package/test/suite/urlencoded.test.ts +0 -23
- package/test/suite/users.test.ts +0 -76
- package/todo.md +0 -9
- package/tsconfig.json +0 -24
- package/vitest.config.ts +0 -17
@@ -1,388 +0,0 @@
|
|
1
|
-
---
|
2
|
-
sidebar_position: 6
|
3
|
-
---
|
4
|
-
|
5
|
-
# Helmet Plugin
|
6
|
-
|
7
|
-
The Helmet plugin sets various HTTP headers to help protect your Balda.js application from well-known web vulnerabilities. It's a security middleware that helps secure your app by setting several HTTP headers.
|
8
|
-
|
9
|
-
## Features
|
10
|
-
|
11
|
-
- **Security Headers**: Sets various security-related HTTP headers
|
12
|
-
- **Configurable Options**: Customize which headers to enable/disable
|
13
|
-
- **Production Ready**: Optimized security settings for production
|
14
|
-
- **Easy Integration**: Simple configuration with sensible defaults
|
15
|
-
- **Comprehensive Protection**: Covers multiple attack vectors
|
16
|
-
|
17
|
-
## Basic Configuration
|
18
|
-
|
19
|
-
### Simple Setup
|
20
|
-
|
21
|
-
```typescript
|
22
|
-
import { Server } from 'balda-js';
|
23
|
-
|
24
|
-
const server = new Server({
|
25
|
-
port: 3000,
|
26
|
-
plugins: {
|
27
|
-
helmet: {}
|
28
|
-
}
|
29
|
-
});
|
30
|
-
```
|
31
|
-
|
32
|
-
### Disable Helmet
|
33
|
-
|
34
|
-
```typescript
|
35
|
-
const server = new Server({
|
36
|
-
port: 3000,
|
37
|
-
plugins: {
|
38
|
-
helmet: false
|
39
|
-
}
|
40
|
-
});
|
41
|
-
```
|
42
|
-
|
43
|
-
## Configuration Options
|
44
|
-
|
45
|
-
### Default Configuration
|
46
|
-
|
47
|
-
```typescript
|
48
|
-
helmet: {
|
49
|
-
dnsPrefetchControl: true,
|
50
|
-
frameguard: { action: "SAMEORIGIN" },
|
51
|
-
hsts: { maxAge: 15552000, includeSubDomains: true, preload: false },
|
52
|
-
contentTypeOptions: true,
|
53
|
-
ieNoOpen: true,
|
54
|
-
xssFilter: true,
|
55
|
-
referrerPolicy: "no-referrer",
|
56
|
-
crossOriginResourcePolicy: "same-origin",
|
57
|
-
crossOriginOpenerPolicy: "same-origin",
|
58
|
-
crossOriginEmbedderPolicy: "require-corp",
|
59
|
-
contentSecurityPolicy: false
|
60
|
-
}
|
61
|
-
```
|
62
|
-
|
63
|
-
### Custom Configuration
|
64
|
-
|
65
|
-
```typescript
|
66
|
-
const server = new Server({
|
67
|
-
port: 3000,
|
68
|
-
plugins: {
|
69
|
-
helmet: {
|
70
|
-
contentSecurityPolicy: {
|
71
|
-
directives: {
|
72
|
-
defaultSrc: ["'self'"],
|
73
|
-
styleSrc: ["'self'", "'unsafe-inline'"],
|
74
|
-
scriptSrc: ["'self'"],
|
75
|
-
imgSrc: ["'self'", "data:", "https:"]
|
76
|
-
}
|
77
|
-
},
|
78
|
-
hsts: {
|
79
|
-
maxAge: 31536000, // 1 year
|
80
|
-
includeSubDomains: true,
|
81
|
-
preload: true
|
82
|
-
}
|
83
|
-
}
|
84
|
-
}
|
85
|
-
});
|
86
|
-
```
|
87
|
-
|
88
|
-
## Security Headers Explained
|
89
|
-
|
90
|
-
### Content Security Policy (CSP)
|
91
|
-
|
92
|
-
```typescript
|
93
|
-
helmet: {
|
94
|
-
contentSecurityPolicy: {
|
95
|
-
directives: {
|
96
|
-
defaultSrc: ["'self'"],
|
97
|
-
styleSrc: ["'self'", "'unsafe-inline'", "https://fonts.googleapis.com"],
|
98
|
-
scriptSrc: ["'self'", "https://cdn.jsdelivr.net"],
|
99
|
-
imgSrc: ["'self'", "data:", "https:"],
|
100
|
-
fontSrc: ["'self'", "https://fonts.gstatic.com"],
|
101
|
-
connectSrc: ["'self'", "https://api.example.com"],
|
102
|
-
frameSrc: ["'none'"],
|
103
|
-
objectSrc: ["'none'"],
|
104
|
-
mediaSrc: ["'self'"],
|
105
|
-
manifestSrc: ["'self'"]
|
106
|
-
}
|
107
|
-
}
|
108
|
-
}
|
109
|
-
```
|
110
|
-
|
111
|
-
### HTTP Strict Transport Security (HSTS)
|
112
|
-
|
113
|
-
```typescript
|
114
|
-
helmet: {
|
115
|
-
hsts: {
|
116
|
-
maxAge: 31536000, // 1 year
|
117
|
-
includeSubDomains: true, // Apply to subdomains
|
118
|
-
preload: true // Include in browser preload lists
|
119
|
-
}
|
120
|
-
}
|
121
|
-
```
|
122
|
-
|
123
|
-
### Frame Options
|
124
|
-
|
125
|
-
```typescript
|
126
|
-
helmet: {
|
127
|
-
frameguard: {
|
128
|
-
action: "DENY" // Prevent embedding in frames
|
129
|
-
}
|
130
|
-
}
|
131
|
-
|
132
|
-
// Or use string values
|
133
|
-
helmet: {
|
134
|
-
frameguard: "DENY" // Same as above
|
135
|
-
}
|
136
|
-
```
|
137
|
-
|
138
|
-
### XSS Protection
|
139
|
-
|
140
|
-
```typescript
|
141
|
-
helmet: {
|
142
|
-
xssFilter: true // Enable XSS protection
|
143
|
-
}
|
144
|
-
```
|
145
|
-
|
146
|
-
### Content Type Options
|
147
|
-
|
148
|
-
```typescript
|
149
|
-
helmet: {
|
150
|
-
contentTypeOptions: true // Prevent MIME type sniffing
|
151
|
-
}
|
152
|
-
```
|
153
|
-
|
154
|
-
## Usage Examples
|
155
|
-
|
156
|
-
### Basic Security Setup
|
157
|
-
|
158
|
-
```typescript
|
159
|
-
const server = new Server({
|
160
|
-
port: 3000,
|
161
|
-
plugins: {
|
162
|
-
helmet: {
|
163
|
-
contentSecurityPolicy: false, // Disable CSP for development
|
164
|
-
hsts: false // Disable HSTS for HTTP
|
165
|
-
}
|
166
|
-
}
|
167
|
-
});
|
168
|
-
```
|
169
|
-
|
170
|
-
### Production Security Configuration
|
171
|
-
|
172
|
-
```typescript
|
173
|
-
const isProduction = process.env.NODE_ENV === 'production';
|
174
|
-
|
175
|
-
const server = new Server({
|
176
|
-
port: 3000,
|
177
|
-
plugins: {
|
178
|
-
helmet: {
|
179
|
-
contentSecurityPolicy: isProduction ? {
|
180
|
-
directives: {
|
181
|
-
defaultSrc: ["'self'"],
|
182
|
-
styleSrc: ["'self'", "'unsafe-inline'"],
|
183
|
-
scriptSrc: ["'self'"],
|
184
|
-
imgSrc: ["'self'", "data:", "https:"],
|
185
|
-
fontSrc: ["'self'", "https://fonts.gstatic.com"],
|
186
|
-
connectSrc: ["'self'"],
|
187
|
-
frameSrc: ["'none'"],
|
188
|
-
objectSrc: ["'none'"]
|
189
|
-
}
|
190
|
-
} : false,
|
191
|
-
hsts: isProduction ? {
|
192
|
-
maxAge: 31536000,
|
193
|
-
includeSubDomains: true,
|
194
|
-
preload: true
|
195
|
-
} : false,
|
196
|
-
frameguard: { action: "DENY" },
|
197
|
-
xssFilter: true,
|
198
|
-
contentTypeOptions: true,
|
199
|
-
referrerPolicy: "strict-origin-when-cross-origin"
|
200
|
-
}
|
201
|
-
}
|
202
|
-
});
|
203
|
-
```
|
204
|
-
|
205
|
-
### API-Focused Configuration
|
206
|
-
|
207
|
-
```typescript
|
208
|
-
const server = new Server({
|
209
|
-
port: 3000,
|
210
|
-
plugins: {
|
211
|
-
helmet: {
|
212
|
-
contentSecurityPolicy: false, // APIs don't need CSP
|
213
|
-
hsts: {
|
214
|
-
maxAge: 31536000,
|
215
|
-
includeSubDomains: true
|
216
|
-
},
|
217
|
-
frameguard: { action: "DENY" },
|
218
|
-
xssFilter: true,
|
219
|
-
contentTypeOptions: true,
|
220
|
-
referrerPolicy: "no-referrer"
|
221
|
-
}
|
222
|
-
}
|
223
|
-
});
|
224
|
-
```
|
225
|
-
|
226
|
-
### Web Application Configuration
|
227
|
-
|
228
|
-
```typescript
|
229
|
-
const server = new Server({
|
230
|
-
port: 3000,
|
231
|
-
plugins: {
|
232
|
-
helmet: {
|
233
|
-
contentSecurityPolicy: {
|
234
|
-
directives: {
|
235
|
-
defaultSrc: ["'self'"],
|
236
|
-
styleSrc: ["'self'", "'unsafe-inline'", "https://fonts.googleapis.com"],
|
237
|
-
scriptSrc: ["'self'", "https://cdn.jsdelivr.net"],
|
238
|
-
imgSrc: ["'self'", "data:", "https:"],
|
239
|
-
fontSrc: ["'self'", "https://fonts.gstatic.com"],
|
240
|
-
connectSrc: ["'self'", "wss:"],
|
241
|
-
frameSrc: ["'self'"],
|
242
|
-
objectSrc: ["'none'"],
|
243
|
-
mediaSrc: ["'self'"],
|
244
|
-
manifestSrc: ["'self'"]
|
245
|
-
}
|
246
|
-
},
|
247
|
-
hsts: {
|
248
|
-
maxAge: 31536000,
|
249
|
-
includeSubDomains: true,
|
250
|
-
preload: true
|
251
|
-
},
|
252
|
-
frameguard: { action: "SAMEORIGIN" },
|
253
|
-
xssFilter: true,
|
254
|
-
contentTypeOptions: true,
|
255
|
-
referrerPolicy: "strict-origin-when-cross-origin"
|
256
|
-
}
|
257
|
-
}
|
258
|
-
});
|
259
|
-
```
|
260
|
-
|
261
|
-
## Individual Header Configuration
|
262
|
-
|
263
|
-
### DNS Prefetch Control
|
264
|
-
|
265
|
-
```typescript
|
266
|
-
helmet: {
|
267
|
-
dnsPrefetchControl: true // Disable DNS prefetching
|
268
|
-
}
|
269
|
-
```
|
270
|
-
|
271
|
-
### Frame Guard
|
272
|
-
|
273
|
-
```typescript
|
274
|
-
helmet: {
|
275
|
-
frameguard: {
|
276
|
-
action: "DENY" // Prevent all framing
|
277
|
-
}
|
278
|
-
}
|
279
|
-
|
280
|
-
// Available actions:
|
281
|
-
// "DENY" - Prevent all framing
|
282
|
-
// "SAMEORIGIN" - Allow same-origin framing
|
283
|
-
// "ALLOW-FROM uri" - Allow framing from specific URI
|
284
|
-
```
|
285
|
-
|
286
|
-
### HSTS Configuration
|
287
|
-
|
288
|
-
```typescript
|
289
|
-
helmet: {
|
290
|
-
hsts: {
|
291
|
-
maxAge: 31536000, // Time in seconds
|
292
|
-
includeSubDomains: true, // Apply to subdomains
|
293
|
-
preload: true // Include in preload lists
|
294
|
-
}
|
295
|
-
}
|
296
|
-
```
|
297
|
-
|
298
|
-
### Content Type Options
|
299
|
-
|
300
|
-
```typescript
|
301
|
-
helmet: {
|
302
|
-
contentTypeOptions: true // Prevent MIME type sniffing
|
303
|
-
}
|
304
|
-
```
|
305
|
-
|
306
|
-
### IE No Open
|
307
|
-
|
308
|
-
```typescript
|
309
|
-
helmet: {
|
310
|
-
ieNoOpen: true // Prevent IE from executing downloads
|
311
|
-
}
|
312
|
-
```
|
313
|
-
|
314
|
-
### XSS Filter
|
315
|
-
|
316
|
-
```typescript
|
317
|
-
helmet: {
|
318
|
-
xssFilter: true // Enable XSS protection
|
319
|
-
}
|
320
|
-
```
|
321
|
-
|
322
|
-
### Referrer Policy
|
323
|
-
|
324
|
-
```typescript
|
325
|
-
helmet: {
|
326
|
-
referrerPolicy: "strict-origin-when-cross-origin"
|
327
|
-
}
|
328
|
-
|
329
|
-
// Available policies:
|
330
|
-
// "no-referrer"
|
331
|
-
// "no-referrer-when-downgrade"
|
332
|
-
// "origin"
|
333
|
-
// "origin-when-cross-origin"
|
334
|
-
// "same-origin"
|
335
|
-
// "strict-origin"
|
336
|
-
// "strict-origin-when-cross-origin"
|
337
|
-
// "unsafe-url"
|
338
|
-
```
|
339
|
-
|
340
|
-
### Cross-Origin Policies
|
341
|
-
|
342
|
-
```typescript
|
343
|
-
helmet: {
|
344
|
-
crossOriginResourcePolicy: "same-origin",
|
345
|
-
crossOriginOpenerPolicy: "same-origin",
|
346
|
-
crossOriginEmbedderPolicy: "require-corp"
|
347
|
-
}
|
348
|
-
```
|
349
|
-
|
350
|
-
## Environment-Based Configuration
|
351
|
-
|
352
|
-
### Development vs Production
|
353
|
-
|
354
|
-
```typescript
|
355
|
-
const isProduction = process.env.NODE_ENV === 'production';
|
356
|
-
|
357
|
-
const helmetConfig = isProduction ? {
|
358
|
-
contentSecurityPolicy: {
|
359
|
-
directives: {
|
360
|
-
defaultSrc: ["'self'"],
|
361
|
-
styleSrc: ["'self'", "'unsafe-inline'"],
|
362
|
-
scriptSrc: ["'self'"],
|
363
|
-
imgSrc: ["'self'", "data:", "https:"]
|
364
|
-
}
|
365
|
-
},
|
366
|
-
hsts: {
|
367
|
-
maxAge: 31536000,
|
368
|
-
includeSubDomains: true,
|
369
|
-
preload: true
|
370
|
-
},
|
371
|
-
frameguard: { action: "DENY" },
|
372
|
-
xssFilter: true,
|
373
|
-
contentTypeOptions: true
|
374
|
-
} : {
|
375
|
-
contentSecurityPolicy: false,
|
376
|
-
hsts: false,
|
377
|
-
frameguard: { action: "SAMEORIGIN" },
|
378
|
-
xssFilter: true,
|
379
|
-
contentTypeOptions: true
|
380
|
-
};
|
381
|
-
|
382
|
-
const server = new Server({
|
383
|
-
port: 3000,
|
384
|
-
plugins: {
|
385
|
-
helmet: helmetConfig
|
386
|
-
}
|
387
|
-
});
|
388
|
-
```
|
@@ -1,338 +0,0 @@
|
|
1
|
-
---
|
2
|
-
sidebar_position: 3
|
3
|
-
---
|
4
|
-
|
5
|
-
# JSON Plugin
|
6
|
-
|
7
|
-
The JSON plugin parses incoming JSON request bodies and populates `req.body` with the parsed data. It automatically handles content-type detection and provides configurable size limits and error handling.
|
8
|
-
|
9
|
-
## Features
|
10
|
-
|
11
|
-
- **Automatic Content-Type Detection**: Parses requests with `application/json` content type
|
12
|
-
- **Configurable Size Limits**: Set maximum body size to prevent memory issues
|
13
|
-
- **Encoding Support**: Support for various text encodings
|
14
|
-
- **Error Handling**: Graceful handling of malformed JSON
|
15
|
-
- **Empty Body Handling**: Configurable behavior for empty request bodies
|
16
|
-
|
17
|
-
## Basic Configuration
|
18
|
-
|
19
|
-
### Simple Setup
|
20
|
-
|
21
|
-
```typescript
|
22
|
-
import { Server } from 'balda-js';
|
23
|
-
|
24
|
-
const server = new Server({
|
25
|
-
port: 3000,
|
26
|
-
plugins: {
|
27
|
-
json: {
|
28
|
-
sizeLimit: '10mb'
|
29
|
-
}
|
30
|
-
}
|
31
|
-
});
|
32
|
-
```
|
33
|
-
|
34
|
-
### Default Configuration
|
35
|
-
|
36
|
-
```typescript
|
37
|
-
const server = new Server({
|
38
|
-
port: 3000,
|
39
|
-
plugins: {
|
40
|
-
json: {
|
41
|
-
sizeLimit: 5 * 1024 * 1024, // 5MB
|
42
|
-
parseEmptyBodyAsObject: false,
|
43
|
-
encoding: 'utf-8'
|
44
|
-
}
|
45
|
-
}
|
46
|
-
});
|
47
|
-
```
|
48
|
-
|
49
|
-
## Configuration Options
|
50
|
-
|
51
|
-
### Size Limit
|
52
|
-
|
53
|
-
```typescript
|
54
|
-
// Using bytes
|
55
|
-
json: {
|
56
|
-
sizeLimit: 1024 * 1024 // 1MB
|
57
|
-
}
|
58
|
-
|
59
|
-
// Using string notation
|
60
|
-
json: {
|
61
|
-
sizeLimit: '10mb'
|
62
|
-
}
|
63
|
-
|
64
|
-
// Large payloads
|
65
|
-
json: {
|
66
|
-
sizeLimit: 50 * 1024 * 1024 // 50MB
|
67
|
-
}
|
68
|
-
```
|
69
|
-
|
70
|
-
### Empty Body Handling
|
71
|
-
|
72
|
-
```typescript
|
73
|
-
// Default behavior - empty body becomes undefined
|
74
|
-
json: {
|
75
|
-
parseEmptyBodyAsObject: false
|
76
|
-
}
|
77
|
-
|
78
|
-
// Empty body becomes empty object
|
79
|
-
json: {
|
80
|
-
parseEmptyBodyAsObject: true
|
81
|
-
}
|
82
|
-
```
|
83
|
-
|
84
|
-
### Custom Error Messages
|
85
|
-
|
86
|
-
```typescript
|
87
|
-
json: {
|
88
|
-
sizeLimit: '10mb',
|
89
|
-
customErrorMessage: {
|
90
|
-
status: 413,
|
91
|
-
message: 'Request body too large'
|
92
|
-
}
|
93
|
-
}
|
94
|
-
```
|
95
|
-
|
96
|
-
### Encoding Configuration
|
97
|
-
|
98
|
-
```typescript
|
99
|
-
// UTF-8 (default)
|
100
|
-
json: {
|
101
|
-
encoding: 'utf-8'
|
102
|
-
}
|
103
|
-
|
104
|
-
// UTF-16
|
105
|
-
json: {
|
106
|
-
encoding: 'utf-16le'
|
107
|
-
}
|
108
|
-
|
109
|
-
// Other encodings
|
110
|
-
json: {
|
111
|
-
encoding: 'iso-8859-1'
|
112
|
-
}
|
113
|
-
```
|
114
|
-
|
115
|
-
## Usage Examples
|
116
|
-
|
117
|
-
### Basic JSON Parsing
|
118
|
-
|
119
|
-
```typescript
|
120
|
-
@controller('/api')
|
121
|
-
export class ApiController {
|
122
|
-
@post('/users')
|
123
|
-
async createUser(req: Request, res: Response) {
|
124
|
-
// req.body is automatically parsed JSON
|
125
|
-
const { name, email, age } = req.body;
|
126
|
-
|
127
|
-
const user = await createUser({ name, email, age });
|
128
|
-
res.created(user);
|
129
|
-
}
|
130
|
-
}
|
131
|
-
```
|
132
|
-
|
133
|
-
### Handling Large Payloads
|
134
|
-
|
135
|
-
```typescript
|
136
|
-
const server = new Server({
|
137
|
-
port: 3000,
|
138
|
-
plugins: {
|
139
|
-
json: {
|
140
|
-
sizeLimit: '50mb', // Allow large file uploads
|
141
|
-
customErrorMessage: {
|
142
|
-
status: 413,
|
143
|
-
message: 'File too large'
|
144
|
-
}
|
145
|
-
}
|
146
|
-
}
|
147
|
-
});
|
148
|
-
|
149
|
-
@controller('/api')
|
150
|
-
export class FileController {
|
151
|
-
@post('/upload')
|
152
|
-
async uploadFile(req: Request, res: Response) {
|
153
|
-
// Handle large JSON payloads
|
154
|
-
const fileData = req.body;
|
155
|
-
res.json({ message: 'File uploaded successfully' });
|
156
|
-
}
|
157
|
-
}
|
158
|
-
```
|
159
|
-
|
160
|
-
### Empty Body Scenarios
|
161
|
-
|
162
|
-
```typescript
|
163
|
-
@controller('/api')
|
164
|
-
export class HealthController {
|
165
|
-
@post('/health')
|
166
|
-
async healthCheck(req: Request, res: Response) {
|
167
|
-
if (req.body === undefined) {
|
168
|
-
// Empty body with parseEmptyBodyAsObject: false
|
169
|
-
res.json({ status: 'ok', body: 'empty' });
|
170
|
-
} else if (Object.keys(req.body).length === 0) {
|
171
|
-
// Empty body with parseEmptyBodyAsObject: true
|
172
|
-
res.json({ status: 'ok', body: 'empty object' });
|
173
|
-
} else {
|
174
|
-
res.json({ status: 'ok', body: req.body });
|
175
|
-
}
|
176
|
-
}
|
177
|
-
}
|
178
|
-
```
|
179
|
-
|
180
|
-
## Error Handling
|
181
|
-
|
182
|
-
### Size Limit Exceeded
|
183
|
-
|
184
|
-
```typescript
|
185
|
-
// Request with body larger than sizeLimit
|
186
|
-
// Response: 413 Payload Too Large
|
187
|
-
{
|
188
|
-
"error": "ERR_REQUEST_BODY_TOO_LARGE"
|
189
|
-
}
|
190
|
-
|
191
|
-
// With custom error message
|
192
|
-
{
|
193
|
-
"error": "Request body too large"
|
194
|
-
}
|
195
|
-
```
|
196
|
-
|
197
|
-
### Invalid JSON
|
198
|
-
|
199
|
-
```typescript
|
200
|
-
// Request with malformed JSON
|
201
|
-
// POST /api/users
|
202
|
-
// Content-Type: application/json
|
203
|
-
// Body: { "name": "John", "email": "john@example.com" }
|
204
|
-
|
205
|
-
// Response: 400 Bad Request
|
206
|
-
{
|
207
|
-
"error": "Invalid JSON syntax"
|
208
|
-
}
|
209
|
-
```
|
210
|
-
|
211
|
-
### Invalid Encoding
|
212
|
-
|
213
|
-
```typescript
|
214
|
-
// Request with unsupported encoding
|
215
|
-
// Response: 400 Bad Request
|
216
|
-
{
|
217
|
-
"error": "Invalid request body encoding"
|
218
|
-
}
|
219
|
-
```
|
220
|
-
|
221
|
-
## Content-Type Detection
|
222
|
-
|
223
|
-
The JSON plugin automatically detects and parses requests with the following content types:
|
224
|
-
|
225
|
-
- `application/json`
|
226
|
-
- `application/json; charset=utf-8`
|
227
|
-
- `application/json; charset=UTF-8`
|
228
|
-
|
229
|
-
### Non-JSON Requests
|
230
|
-
|
231
|
-
Requests without `application/json` content type are ignored:
|
232
|
-
|
233
|
-
```typescript
|
234
|
-
// This request will NOT be parsed by the JSON plugin
|
235
|
-
// POST /api/users
|
236
|
-
// Content-Type: application/x-www-form-urlencoded
|
237
|
-
// Body: name=John&email=john@example.com
|
238
|
-
|
239
|
-
@post('/users')
|
240
|
-
async createUser(req: Request, res: Response) {
|
241
|
-
// req.body will be undefined or handled by another parser
|
242
|
-
console.log(req.body); // undefined
|
243
|
-
}
|
244
|
-
```
|
245
|
-
|
246
|
-
## HTTP Method Restrictions
|
247
|
-
|
248
|
-
The JSON plugin only parses bodies for methods that can have a body:
|
249
|
-
|
250
|
-
- **Parsed**: POST, PUT, PATCH
|
251
|
-
- **Ignored**: GET, DELETE, HEAD, OPTIONS
|
252
|
-
|
253
|
-
```typescript
|
254
|
-
@controller('/api')
|
255
|
-
export class UsersController {
|
256
|
-
@get('/users')
|
257
|
-
async getUsers(req: Request, res: Response) {
|
258
|
-
// req.body will be undefined (GET request)
|
259
|
-
res.json({ users: [] });
|
260
|
-
}
|
261
|
-
|
262
|
-
@post('/users')
|
263
|
-
async createUser(req: Request, res: Response) {
|
264
|
-
// req.body will be parsed JSON
|
265
|
-
res.created(req.body);
|
266
|
-
}
|
267
|
-
}
|
268
|
-
```
|
269
|
-
|
270
|
-
## Advanced Configuration
|
271
|
-
|
272
|
-
### Production vs Development
|
273
|
-
|
274
|
-
```typescript
|
275
|
-
const isProduction = process.env.NODE_ENV === 'production';
|
276
|
-
|
277
|
-
const server = new Server({
|
278
|
-
port: 3000,
|
279
|
-
plugins: {
|
280
|
-
json: {
|
281
|
-
sizeLimit: isProduction ? '1mb' : '10mb',
|
282
|
-
parseEmptyBodyAsObject: false,
|
283
|
-
encoding: 'utf-8',
|
284
|
-
customErrorMessage: isProduction ? {
|
285
|
-
status: 413,
|
286
|
-
message: 'Request too large'
|
287
|
-
} : undefined
|
288
|
-
}
|
289
|
-
}
|
290
|
-
});
|
291
|
-
```
|
292
|
-
|
293
|
-
### Multiple Content Types
|
294
|
-
|
295
|
-
```typescript
|
296
|
-
// JSON plugin handles application/json
|
297
|
-
// URL-encoded plugin handles application/x-www-form-urlencoded
|
298
|
-
const server = new Server({
|
299
|
-
port: 3000,
|
300
|
-
plugins: {
|
301
|
-
json: {
|
302
|
-
sizeLimit: '10mb'
|
303
|
-
},
|
304
|
-
urlencoded: {
|
305
|
-
extended: true
|
306
|
-
}
|
307
|
-
}
|
308
|
-
});
|
309
|
-
```
|
310
|
-
|
311
|
-
## Performance Considerations
|
312
|
-
|
313
|
-
### Memory Usage
|
314
|
-
|
315
|
-
```typescript
|
316
|
-
// Be careful with large size limits
|
317
|
-
json: {
|
318
|
-
sizeLimit: '100mb' // Could cause memory issues
|
319
|
-
}
|
320
|
-
|
321
|
-
// Recommended for most applications
|
322
|
-
json: {
|
323
|
-
sizeLimit: '10mb' // Reasonable limit
|
324
|
-
}
|
325
|
-
```
|
326
|
-
|
327
|
-
### Streaming for Large Files
|
328
|
-
|
329
|
-
For very large files, consider using the file upload plugin instead:
|
330
|
-
|
331
|
-
```typescript
|
332
|
-
// For large files, use file upload plugin
|
333
|
-
plugins: {
|
334
|
-
file: {
|
335
|
-
maxFileSize: 50 * 1024 * 1024 // 50MB
|
336
|
-
}
|
337
|
-
}
|
338
|
-
```
|