npm-express

Description
Fast, unopinionated, minimalist web framework for Node.js
Author
tessl
Last updated

How to use

npx @tessl/cli registry install tessl/npm-express@4.21.0

response.md docs/

1
# Response Handling
2
3
Enhanced response object with Express-specific methods for sending responses, setting headers, handling cookies, and content negotiation.
4
5
## Capabilities
6
7
### Response Sending
8
9
Send various types of responses including text, JSON, files, and status codes.
10
11
```javascript { .api }
12
/**
13
* Send response with automatic content type detection
14
* @param {any} [body] - Response body (string, Buffer, object, etc.)
15
* @returns {Response} Response instance for chaining
16
*/
17
res.send(body?: any): Response;
18
19
/**
20
* Send JSON response
21
* @param {any} [obj] - Object to serialize as JSON
22
* @returns {Response} Response instance for chaining
23
*/
24
res.json(obj?: any): Response;
25
26
/**
27
* Send JSONP response for cross-domain requests
28
* @param {any} [obj] - Object to serialize as JSONP
29
* @returns {Response} Response instance for chaining
30
*/
31
res.jsonp(obj?: any): Response;
32
33
/**
34
* Send status code only
35
* @param {number} statusCode - HTTP status code
36
* @returns {Response} Response instance for chaining
37
*/
38
res.sendStatus(statusCode: number): Response;
39
```
40
41
**Usage Examples:**
42
43
```javascript
44
app.get('/text', (req, res) => {
45
res.send('Hello World!');
46
});
47
48
app.get('/html', (req, res) => {
49
res.send('<h1>Hello HTML!</h1>');
50
});
51
52
app.get('/json', (req, res) => {
53
res.json({ message: 'Hello JSON!', timestamp: new Date() });
54
});
55
56
app.get('/jsonp', (req, res) => {
57
res.jsonp({ data: 'JSONP response' });
58
// With callback: /jsonp?callback=myCallback
59
// Returns: myCallback({"data":"JSONP response"});
60
});
61
62
app.get('/status-only', (req, res) => {
63
res.sendStatus(204); // No Content
64
});
65
66
app.post('/created', (req, res) => {
67
res.sendStatus(201); // Created
68
});
69
70
app.get('/not-found', (req, res) => {
71
res.sendStatus(404); // Not Found
72
});
73
```
74
75
### File Handling
76
77
Send files and trigger downloads with proper headers and options.
78
79
```javascript { .api }
80
/**
81
* Send file from file system
82
* @param {string} path - Path to file (absolute or relative to cwd)
83
* @param {SendFileOptions} [options] - File sending options
84
* @param {Function} [callback] - Callback function for completion/errors
85
*/
86
res.sendFile(path: string, options?: SendFileOptions, callback?: (err?: Error) => void): void;
87
88
/**
89
* Trigger file download with Content-Disposition header
90
* @param {string} path - Path to file
91
* @param {string} [filename] - Filename for download (defaults to basename)
92
* @param {SendFileOptions} [options] - File sending options
93
* @param {Function} [callback] - Callback function for completion/errors
94
*/
95
res.download(path: string, filename?: string, options?: SendFileOptions, callback?: (err?: Error) => void): void;
96
97
/**
98
* File sending options
99
*/
100
interface SendFileOptions {
101
/** Maximum age for caching (milliseconds) */
102
maxAge?: number;
103
/** Root directory for relative paths */
104
root?: string;
105
/** Last-Modified header (default: true) */
106
lastModified?: boolean;
107
/** Custom headers to set */
108
headers?: { [key: string]: string };
109
/** Enable dot files (default: false) */
110
dotfiles?: 'allow' | 'deny' | 'ignore';
111
/** Accept ranges (default: true) */
112
acceptRanges?: boolean;
113
/** Cache control immutable (default: false) */
114
immutable?: boolean;
115
}
116
```
117
118
**Usage Examples:**
119
120
```javascript
121
const path = require('path');
122
123
// Send file with absolute path
124
app.get('/download/report', (req, res) => {
125
const filePath = path.join(__dirname, 'reports', 'monthly.pdf');
126
res.sendFile(filePath, (err) => {
127
if (err) {
128
res.status(404).send('File not found');
129
}
130
});
131
});
132
133
// Send file with options
134
app.get('/static/:filename', (req, res) => {
135
res.sendFile(req.params.filename, {
136
root: path.join(__dirname, 'public'),
137
maxAge: 86400000, // 1 day
138
headers: {
139
'X-Sent': 'true'
140
}
141
}, (err) => {
142
if (err) {
143
res.status(err.status || 500).send('Error sending file');
144
}
145
});
146
});
147
148
// Trigger file download
149
app.get('/download/:filename', (req, res) => {
150
const filePath = path.join(__dirname, 'downloads', req.params.filename);
151
res.download(filePath, (err) => {
152
if (err) {
153
res.status(404).send('File not found');
154
}
155
});
156
});
157
158
// Download with custom filename
159
app.get('/export/users', (req, res) => {
160
const filePath = path.join(__dirname, 'temp', 'users-export.csv');
161
res.download(filePath, 'my-users.csv');
162
});
163
```
164
165
### Status and Headers
166
167
Set response status codes and headers for proper HTTP communication.
168
169
```javascript { .api }
170
/**
171
* Set response status code
172
* @param {number} statusCode - HTTP status code
173
* @returns {Response} Response instance for chaining
174
*/
175
res.status(statusCode: number): Response;
176
177
/**
178
* Set response header(s)
179
* @param {string | object} field - Header name or header object
180
* @param {string} [value] - Header value (when field is string)
181
* @returns {Response} Response instance for chaining
182
*/
183
res.set(field: string | { [key: string]: string }, value?: string): Response;
184
185
/**
186
* Alias for res.set()
187
* @param {string | object} field - Header name or header object
188
* @param {string} [value] - Header value (when field is string)
189
* @returns {Response} Response instance for chaining
190
*/
191
res.header(field: string | { [key: string]: string }, value?: string): Response;
192
193
/**
194
* Get response header value
195
* @param {string} field - Header name
196
* @returns {string | undefined} Header value or undefined
197
*/
198
res.get(field: string): string | undefined;
199
200
/**
201
* Append value to response header
202
* @param {string} field - Header name
203
* @param {string | string[]} value - Value(s) to append
204
* @returns {Response} Response instance for chaining
205
*/
206
res.append(field: string, value: string | string[]): Response;
207
```
208
209
**Usage Examples:**
210
211
```javascript
212
// Set status and send response
213
app.get('/api/users/:id', (req, res) => {
214
const user = findUser(req.params.id);
215
216
if (!user) {
217
return res.status(404).json({ error: 'User not found' });
218
}
219
220
res.status(200).json(user);
221
});
222
223
// Set individual headers
224
app.get('/api/data', (req, res) => {
225
res.set('X-API-Version', '1.0');
226
res.set('X-Rate-Limit', '1000');
227
res.json({ data: 'example' });
228
});
229
230
// Set multiple headers at once
231
app.get('/secure-data', (req, res) => {
232
res.set({
233
'X-Content-Type-Options': 'nosniff',
234
'X-Frame-Options': 'DENY',
235
'X-XSS-Protection': '1; mode=block'
236
});
237
res.json({ sensitive: 'data' });
238
});
239
240
// Append to headers
241
app.get('/cors-endpoint', (req, res) => {
242
res.append('Access-Control-Allow-Methods', 'GET');
243
res.append('Access-Control-Allow-Methods', 'POST');
244
res.json({ message: 'CORS enabled' });
245
});
246
247
// Check existing headers
248
app.use((req, res, next) => {
249
res.set('X-Request-ID', generateId());
250
next();
251
});
252
253
app.get('/check-headers', (req, res) => {
254
const requestId = res.get('X-Request-ID');
255
res.json({ requestId });
256
});
257
```
258
259
### Content Type Management
260
261
Set and manage response content types with proper MIME type handling.
262
263
```javascript { .api }
264
/**
265
* Set Content-Type header based on file extension or MIME type
266
* @param {string} type - File extension or MIME type
267
* @returns {Response} Response instance for chaining
268
*/
269
res.type(type: string): Response;
270
271
/**
272
* Set Vary header for content negotiation
273
* @param {string} field - Header field to vary on
274
* @returns {Response} Response instance for chaining
275
*/
276
res.vary(field: string): Response;
277
278
/**
279
* Set response format based on Accept header
280
* @param {Object} obj - Object with format handlers
281
* @returns {Response} Response instance for chaining
282
*/
283
res.format(obj: { [key: string]: () => void }): Response;
284
```
285
286
**Usage Examples:**
287
288
```javascript
289
// Set content type by extension
290
app.get('/xml-data', (req, res) => {
291
res.type('xml');
292
res.send('<data>XML content</data>');
293
});
294
295
// Set content type by MIME type
296
app.get('/pdf-report', (req, res) => {
297
res.type('application/pdf');
298
// Send PDF data...
299
});
300
301
// Content negotiation with format
302
app.get('/api/users', (req, res) => {
303
const users = getUsers();
304
305
res.format({
306
'text/plain': () => {
307
res.send(users.map(u => u.name).join('\n'));
308
},
309
'text/html': () => {
310
res.send('<ul>' + users.map(u => `<li>${u.name}</li>`).join('') + '</ul>');
311
},
312
'application/json': () => {
313
res.json(users);
314
},
315
'application/xml': () => {
316
res.type('xml');
317
res.send(convertToXML(users));
318
},
319
'default': () => {
320
res.status(406).send('Not Acceptable');
321
}
322
});
323
});
324
325
// Set Vary header for caching
326
app.get('/api/content', (req, res) => {
327
res.vary('Accept-Encoding');
328
res.vary('Accept-Language');
329
res.json({ content: 'varies by encoding and language' });
330
});
331
```
332
333
### Redirects
334
335
Redirect requests to different URLs with proper status codes.
336
337
```javascript { .api }
338
/**
339
* Redirect request to specified URL with optional status code
340
* @param {number} [status] - HTTP status code (default: 302)
341
* @param {string} url - URL to redirect to
342
*/
343
res.redirect(status: number, url: string): void;
344
res.redirect(url: string): void;
345
```
346
347
**Usage Examples:**
348
349
```javascript
350
// Temporary redirect (302)
351
app.get('/old-page', (req, res) => {
352
res.redirect('/new-page');
353
});
354
355
// Permanent redirect (301)
356
app.get('/legacy-api', (req, res) => {
357
res.redirect(301, '/api/v2');
358
});
359
360
// Redirect with query parameters
361
app.get('/search', (req, res) => {
362
if (!req.query.q) {
363
return res.redirect('/search?q=default');
364
}
365
res.send(`Searching for: ${req.query.q}`);
366
});
367
368
// Conditional redirects
369
app.get('/dashboard', (req, res) => {
370
if (!req.user) {
371
return res.redirect('/login');
372
}
373
res.send('Dashboard content');
374
});
375
376
// External redirects
377
app.get('/external', (req, res) => {
378
res.redirect('https://external-site.com/page');
379
});
380
```
381
382
### Cookie Management
383
384
Set and clear cookies with various options for session management and user preferences.
385
386
```javascript { .api }
387
/**
388
* Set cookie with name, value, and options
389
* @param {string} name - Cookie name
390
* @param {string} value - Cookie value
391
* @param {CookieOptions} [options] - Cookie options
392
* @returns {Response} Response instance for chaining
393
*/
394
res.cookie(name: string, value: string, options?: CookieOptions): Response;
395
396
/**
397
* Clear cookie by name with optional options
398
* @param {string} name - Cookie name to clear
399
* @param {CookieOptions} [options] - Cookie options (must match original)
400
* @returns {Response} Response instance for chaining
401
*/
402
res.clearCookie(name: string, options?: CookieOptions): Response;
403
404
/**
405
* Cookie configuration options
406
*/
407
interface CookieOptions {
408
/** Cookie domain */
409
domain?: string;
410
/** Cookie path (default: '/') */
411
path?: string;
412
/** Secure cookie (HTTPS only) */
413
secure?: boolean;
414
/** HTTP only cookie (not accessible via JavaScript) */
415
httpOnly?: boolean;
416
/** Expiration date */
417
expires?: Date;
418
/** Max age in milliseconds */
419
maxAge?: number;
420
/** SameSite attribute */
421
sameSite?: boolean | 'lax' | 'strict' | 'none';
422
/** Signed cookie (requires cookie-parser secret) */
423
signed?: boolean;
424
}
425
```
426
427
**Usage Examples:**
428
429
```javascript
430
// Basic cookie
431
app.get('/set-cookie', (req, res) => {
432
res.cookie('username', 'john_doe');
433
res.send('Cookie set');
434
});
435
436
// Cookie with options
437
app.post('/login', (req, res) => {
438
res.cookie('session_id', generateSessionId(), {
439
httpOnly: true,
440
secure: process.env.NODE_ENV === 'production',
441
maxAge: 24 * 60 * 60 * 1000, // 24 hours
442
sameSite: 'strict'
443
});
444
res.json({ message: 'Logged in successfully' });
445
});
446
447
// Persistent cookie
448
app.get('/remember-me', (req, res) => {
449
const expires = new Date();
450
expires.setFullYear(expires.getFullYear() + 1); // 1 year from now
451
452
res.cookie('remember_token', 'abc123', {
453
expires: expires,
454
httpOnly: true,
455
secure: true
456
});
457
res.send('Remember me cookie set');
458
});
459
460
// Clear cookie
461
app.post('/logout', (req, res) => {
462
res.clearCookie('session_id');
463
res.clearCookie('remember_token');
464
res.json({ message: 'Logged out successfully' });
465
});
466
467
// Clear cookie with matching options
468
app.get('/clear-secure-cookie', (req, res) => {
469
res.clearCookie('secure_data', {
470
path: '/admin',
471
secure: true,
472
httpOnly: true
473
});
474
res.send('Secure cookie cleared');
475
});
476
```
477
478
### Template Rendering
479
480
Render views using configured template engines with local variables.
481
482
```javascript { .api }
483
/**
484
* Render view template with locals and send as response
485
* @param {string} view - View name/path
486
* @param {Object} [locals] - Local variables for template
487
* @param {Function} [callback] - Callback function for completion/errors
488
*/
489
res.render(view: string, locals?: any, callback?: (err: Error | null, html?: string) => void): void;
490
```
491
492
**Usage Examples:**
493
494
```javascript
495
// Set view engine
496
app.set('view engine', 'ejs');
497
app.set('views', './views');
498
499
// Basic view rendering
500
app.get('/', (req, res) => {
501
res.render('index');
502
});
503
504
// Render with local variables
505
app.get('/user/:id', (req, res) => {
506
const user = findUser(req.params.id);
507
res.render('user-profile', {
508
user: user,
509
title: `${user.name}'s Profile`,
510
currentYear: new Date().getFullYear()
511
});
512
});
513
514
// Render with callback
515
app.get('/report', (req, res) => {
516
const data = generateReportData();
517
518
res.render('report-template', { data }, (err, html) => {
519
if (err) {
520
res.status(500).send('Error rendering report');
521
} else {
522
// Optionally modify HTML before sending
523
const modifiedHtml = html.replace('{{timestamp}}', new Date().toISOString());
524
res.send(modifiedHtml);
525
}
526
});
527
});
528
529
// Dynamic view selection
530
app.get('/page/:template', (req, res) => {
531
const allowedTemplates = ['about', 'contact', 'services'];
532
const template = req.params.template;
533
534
if (!allowedTemplates.includes(template)) {
535
return res.status(404).render('404');
536
}
537
538
res.render(`pages/${template}`, {
539
title: template.charAt(0).toUpperCase() + template.slice(1),
540
layout: 'main'
541
});
542
});
543
```
544
545
### Additional Response Methods
546
547
Set specialized headers and handle specific response scenarios.
548
549
```javascript { .api }
550
/**
551
* Set Link header for resource relationships
552
* @param {Object} links - Object with link relationships
553
* @returns {Response} Response instance for chaining
554
*/
555
res.links(links: { [rel: string]: string }): Response;
556
557
/**
558
* Set Location header (typically used with redirects)
559
* @param {string} path - Location path or URL
560
* @returns {Response} Response instance for chaining
561
*/
562
res.location(path: string): Response;
563
564
/**
565
* Set Content-Disposition attachment header
566
* @param {string} [filename] - Optional filename for attachment
567
* @returns {Response} Response instance for chaining
568
*/
569
res.attachment(filename?: string): Response;
570
```
571
572
**Usage Examples:**
573
574
```javascript
575
// Set link relationships
576
app.get('/api/users', (req, res) => {
577
res.links({
578
next: '/api/users?page=2',
579
prev: '/api/users?page=1',
580
first: '/api/users?page=1',
581
last: '/api/users?page=10'
582
});
583
res.json({ users: [] });
584
});
585
586
// Set location header
587
app.post('/api/users', (req, res) => {
588
const user = createUser(req.body);
589
res.location(`/api/users/${user.id}`);
590
res.status(201).json(user);
591
});
592
593
// Set attachment header
594
app.get('/export/data', (req, res) => {
595
res.attachment('data-export.csv');
596
res.send('id,name,email\n1,John,john@example.com');
597
});
598
599
app.get('/download/report', (req, res) => {
600
res.attachment(); // Uses original filename
601
res.sendFile(path.join(__dirname, 'reports', 'monthly.pdf'));
602
});
603
```
604
605
## Response Object Properties
606
607
```javascript { .api }
608
/**
609
* Express response object extends Node.js ServerResponse
610
*/
611
interface Response {
612
/** Reference to Express application instance */
613
app: Application;
614
/** Response local variables available to views */
615
locals: { [key: string]: any };
616
/** Response headers sent status */
617
headersSent: boolean;
618
}
619
```
620
621
**Usage Examples:**
622
623
```javascript
624
// Use response locals for view data
625
app.use((req, res, next) => {
626
res.locals.currentUser = req.user;
627
res.locals.siteName = 'My App';
628
next();
629
});
630
631
// Check if headers were already sent
632
app.get('/delayed-response', (req, res) => {
633
setTimeout(() => {
634
if (!res.headersSent) {
635
res.json({ message: 'Delayed response' });
636
}
637
}, 5000);
638
});
639
```