0
# Middleware System
1
2
LoopBack's Express-compatible middleware system provides request processing capabilities with LoopBack-specific middleware for REST APIs, authentication, error handling, and request lifecycle management through configurable middleware phases.
3
4
## Capabilities
5
6
### Core REST Middleware
7
8
Essential middleware for REST API functionality and request processing.
9
10
```javascript { .api }
11
/**
12
* REST API middleware for exposing models as REST endpoints
13
* @param {Object} options - REST middleware options
14
* @param {string} options.restApiRoot - REST API base path (default: '/api')
15
* @param {boolean} options.handleErrors - Handle errors automatically
16
* @param {boolean} options.handleUnknownPaths - Handle unknown paths
17
* @returns {Function} Express middleware function
18
*/
19
loopback.rest(options);
20
21
/**
22
* Status endpoint middleware for health checks
23
* @param {Object} options - Status middleware options
24
* @param {string} options.endpoint - Status endpoint path (default: '/status')
25
* @returns {Function} Express middleware function
26
*/
27
loopback.status(options);
28
```
29
30
**Usage Example:**
31
32
```javascript
33
const app = loopback();
34
35
// Enable REST API
36
app.use(loopback.rest({
37
restApiRoot: '/api',
38
handleErrors: true
39
}));
40
41
// Add status endpoint
42
app.use(loopback.status({
43
endpoint: '/health'
44
}));
45
46
// Start server
47
app.listen(3000);
48
// Now available: GET /api/books, POST /api/books, etc.
49
// Health check: GET /health
50
```
51
52
### Authentication Middleware
53
54
Token-based authentication middleware for securing API endpoints.
55
56
```javascript { .api }
57
/**
58
* Token authentication middleware
59
* @param {Object} options - Token middleware options
60
* @param {boolean} options.enableDoublecheck - Enable double-check mode
61
* @param {boolean} options.overwriteExistingToken - Overwrite existing token
62
* @param {string[]} options.searchDefaultTokenKeys - Default token search keys
63
* @param {Object} options.cookies - Cookie options
64
* @param {Object} options.headers - Header options
65
* @param {Object} options.params - Parameter options
66
* @returns {Function} Express middleware function
67
*/
68
loopback.token(options);
69
70
/**
71
* Context middleware for maintaining request context
72
* @deprecated Removed in LoopBack 3.0
73
* @param {Object} options - Context options
74
* @returns {Function} Express middleware function
75
*/
76
loopback.context(options);
77
```
78
79
**Usage Example:**
80
81
```javascript
82
const app = loopback();
83
84
// Enable request context - DEPRECATED (removed in v3.0)
85
// app.use(loopback.context());
86
87
// Enable token authentication
88
app.use(loopback.token({
89
searchDefaultTokenKeys: ['access_token', 'authorization'],
90
cookies: ['access_token'],
91
headers: ['authorization', 'x-access-token'],
92
params: ['access_token']
93
}));
94
95
// Protected routes will now require valid access token
96
app.use('/api', loopback.rest());
97
```
98
99
### Error Handling Middleware
100
101
Comprehensive error handling and formatting for API responses.
102
103
```javascript { .api }
104
/**
105
* Error handler middleware for formatting and logging errors
106
* @deprecated Use 'strong-error-handler' package instead
107
* @param {Object} options - Error handler options
108
* @param {boolean} options.debug - Enable debug mode
109
* @param {boolean} options.log - Enable error logging
110
* @param {Function} options.defaultType - Default error type
111
* @param {Object} options.rootProperty - Root property for error response
112
* @returns {Function} Express error middleware function
113
*/
114
loopback.errorHandler(options);
115
116
/**
117
* 404 Not Found handler for unmatched routes
118
* @param {Object} options - URL not found options
119
* @returns {Function} Express middleware function
120
*/
121
loopback.urlNotFound(options);
122
```
123
124
**Usage Example:**
125
126
```javascript
127
const app = loopback();
128
129
// Application routes
130
app.use('/api', loopback.rest());
131
132
// 404 handler (before error handler)
133
app.use(loopback.urlNotFound());
134
135
// Error handler (should be last) - DEPRECATED
136
// Use 'strong-error-handler' package instead:
137
// const errorHandler = require('strong-error-handler');
138
// app.use(errorHandler({ debug: process.env.NODE_ENV !== 'production' }));
139
app.use(loopback.errorHandler({
140
debug: process.env.NODE_ENV !== 'production',
141
log: true
142
}));
143
```
144
145
### Static File Middleware
146
147
Static file serving with LoopBack-specific enhancements.
148
149
```javascript { .api }
150
/**
151
* Static file serving middleware (Express static with LoopBack enhancements)
152
* @param {string} root - Root directory for static files
153
* @param {Object} options - Static middleware options
154
* @param {boolean} options.dotfiles - How to treat dotfiles
155
* @param {string} options.etag - ETag generation
156
* @param {string[]} options.extensions - File extensions
157
* @param {boolean} options.fallthrough - Continue to next middleware on 404
158
* @param {boolean} options.immutable - Set immutable cache header
159
* @param {string|number} options.maxAge - Cache max age
160
* @returns {Function} Express middleware function
161
*/
162
loopback.static(root, options);
163
164
/**
165
* Favicon middleware for serving favicon files
166
* @param {string|Buffer} icon - Path to favicon or favicon buffer
167
* @param {Object} options - Favicon options
168
* @param {string|number} options.maxAge - Cache max age
169
* @returns {Function} Express middleware function
170
*/
171
loopback.favicon(icon, options);
172
```
173
174
**Usage Example:**
175
176
```javascript
177
const path = require('path');
178
const app = loopback();
179
180
// Serve favicon
181
app.use(loopback.favicon(loopback.faviconFile));
182
183
// Serve static files
184
app.use('/public', loopback.static(path.join(__dirname, 'public'), {
185
maxAge: '1d',
186
etag: true
187
}));
188
189
// Default favicon from LoopBack
190
app.use(loopback.favicon(loopback.faviconFile));
191
```
192
193
### Middleware Phase System
194
195
Configure middleware execution phases for fine-grained control over request processing.
196
197
```javascript { .api }
198
/**
199
* Define middleware phases for the application
200
* @param {string|string[]} nameOrArray - Phase name or array of phase names
201
*/
202
app.defineMiddlewarePhases(nameOrArray);
203
204
/**
205
* Register middleware in a specific phase
206
* @param {string} phase - Middleware phase name
207
* @param {string|string[]|RegExp} paths - Optional paths to apply middleware to
208
* @param {Function} handler - Middleware function
209
*/
210
app.middleware(phase, paths, handler);
211
212
/**
213
* Register middleware from configuration object
214
* @param {Function} factory - Middleware factory function
215
* @param {Object} config - Middleware configuration
216
* @param {string} config.phase - Phase to register in
217
* @param {string[]} config.paths - Paths to apply to
218
* @param {Object} config.params - Parameters for factory function
219
*/
220
app.middlewareFromConfig(factory, config);
221
```
222
223
**Built-in Middleware Phases (in order):**
224
225
1. **`initial`** - First phase for initialization and request setup
226
2. **`session`** - Session handling and user session management
227
3. **`auth`** - Authentication and authorization checks
228
4. **`parse`** - Request body parsing and data transformation
229
5. **`routes`** - Application routes and REST API endpoints
230
6. **`files`** - Static file serving and asset delivery
231
7. **`final`** - Error handling and response finalization
232
233
**Usage Example:**
234
235
```javascript
236
const app = loopback();
237
238
// Define custom middleware phases
239
app.defineMiddlewarePhases(['validation', 'transform', 'logging']);
240
241
// Register middleware in specific phases
242
app.middleware('initial', (req, res, next) => {
243
console.log('Request started:', req.method, req.url);
244
next();
245
});
246
247
app.middleware('auth', '/api', loopback.token());
248
249
app.middleware('validation', '/api', (req, res, next) => {
250
// Custom validation logic
251
if (!req.body) {
252
return res.status(400).json({ error: 'Request body required' });
253
}
254
next();
255
});
256
257
app.middleware('routes', loopback.rest());
258
259
app.middleware('final', loopback.errorHandler());
260
```
261
262
### Remote Method Utilities
263
264
Utilities for configuring remote method exposure.
265
266
```javascript { .api }
267
/**
268
* Configure remote method on a function
269
* @param {Function} fn - Function to make remote
270
* @param {Object} options - Remote method options
271
* @param {Object[]} options.accepts - Input parameters
272
* @param {Object} options.returns - Return value description
273
* @param {Object} options.http - HTTP configuration
274
* @param {string} options.http.verb - HTTP verb (get, post, put, delete)
275
* @param {string} options.http.path - HTTP path
276
* @param {number} options.http.status - HTTP status code
277
*/
278
loopback.remoteMethod(fn, options);
279
```
280
281
**Usage Example:**
282
283
```javascript
284
// Define a custom remote method
285
function customOperation(input, callback) {
286
// Custom logic here
287
callback(null, { result: input.toUpperCase() });
288
}
289
290
// Configure as remote method
291
loopback.remoteMethod(customOperation, {
292
accepts: [
293
{ arg: 'input', type: 'string', required: true }
294
],
295
returns: [
296
{ arg: 'result', type: 'object' }
297
],
298
http: {
299
verb: 'post',
300
path: '/custom-operation'
301
}
302
});
303
304
// Add to model
305
const MyModel = loopback.createModel('MyModel');
306
MyModel.customOperation = customOperation;
307
```
308
309
### Template Utilities
310
311
Template rendering utilities for server-side rendering.
312
313
```javascript { .api }
314
/**
315
* Create template renderer function
316
* @param {string} file - Path to template file
317
* @returns {Function} Template rendering function
318
*/
319
loopback.template(file);
320
```
321
322
**Usage Example:**
323
324
```javascript
325
const path = require('path');
326
327
// Create template renderer
328
const renderWelcome = loopback.template(
329
path.join(__dirname, 'views', 'welcome.ejs')
330
);
331
332
// Use in route
333
app.get('/welcome', (req, res) => {
334
const html = renderWelcome({
335
name: req.query.name || 'Guest',
336
title: 'Welcome to LoopBack'
337
});
338
res.send(html);
339
});
340
```
341
342
### Middleware Configuration Types
343
344
Type definitions for middleware configuration objects.
345
346
```javascript { .api }
347
/**
348
* Middleware configuration object
349
*/
350
interface MiddlewareConfig {
351
phase: string; // Middleware phase name
352
paths?: string | string[]; // Paths to apply middleware to
353
params?: Object; // Parameters for middleware factory
354
enabled?: boolean; // Whether middleware is enabled
355
optional?: boolean; // Whether middleware is optional
356
}
357
358
/**
359
* Remote method configuration
360
*/
361
interface RemoteMethodOptions {
362
accepts?: Array<{ // Input parameters
363
arg: string; // Parameter name
364
type: string; // Parameter type
365
required?: boolean; // Whether parameter is required
366
default?: any; // Default value
367
description?: string; // Parameter description
368
http?: Object; // HTTP-specific options
369
}>;
370
returns?: Array<{ // Return values
371
arg: string; // Return value name
372
type: string; // Return value type
373
description?: string; // Return value description
374
root?: boolean; // Whether this is the root return value
375
}>;
376
http?: { // HTTP configuration
377
verb: string; // HTTP verb
378
path?: string; // HTTP path
379
status?: number; // HTTP status code
380
errorStatus?: number; // Error status code
381
};
382
description?: string; // Method description
383
notes?: string; // Additional notes
384
documented?: boolean; // Whether to include in documentation
385
accessType?: string; // Access type for ACL
386
}
387
388
/**
389
* Error handler options
390
*/
391
interface ErrorHandlerOptions {
392
debug?: boolean; // Enable debug mode
393
log?: boolean; // Enable error logging
394
safeFields?: string[]; // Safe fields to include in error response
395
defaultType?: string; // Default error type
396
negotiateContentType?: boolean; // Negotiate content type
397
rootProperty?: string; // Root property for error response
398
}
399
400
/**
401
* Token middleware options
402
*/
403
interface TokenOptions {
404
enableDoublecheck?: boolean; // Enable double-check mode
405
overwriteExistingToken?: boolean; // Overwrite existing token
406
searchDefaultTokenKeys?: string[]; // Default token search keys
407
cookies?: string | string[]; // Cookie names to search
408
headers?: string | string[]; // Header names to search
409
params?: string | string[]; // Parameter names to search
410
bearerTokenBase64Encoded?: boolean; // Whether bearer token is base64 encoded
411
}
412
```