orator-serviceserver-restify 2.0.4 → 2.0.7

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.
@@ -0,0 +1,50 @@
1
+ # Contributing to Retold
2
+
3
+ We welcome contributions to Retold and its modules. This guide covers the expectations and process for contributing.
4
+
5
+ ## Code of Conduct
6
+
7
+ The Retold community values **empathy**, **equity**, **kindness**, and **thoughtfulness**. We expect all participants to treat each other with respect, assume good intent, and engage constructively. These values apply to all interactions: pull requests, issues, discussions, and code review.
8
+
9
+ ## How to Contribute
10
+
11
+ ### Pull Requests
12
+
13
+ Pull requests are the preferred method for contributing changes. To submit one:
14
+
15
+ 1. Fork the module repository you want to change
16
+ 2. Create a branch for your work
17
+ 3. Make your changes, following the code style of the module you are editing
18
+ 4. Ensure your changes have test coverage (see below)
19
+ 5. Open a pull request against the module's main branch
20
+
21
+ **Submitting a pull request does not guarantee it will be accepted.** Maintainers review contributions for fit, quality, and alignment with the project's direction. A PR may be declined, or you may be asked to revise it. This is normal and not a reflection on the quality of your effort.
22
+
23
+ ### Reporting Issues
24
+
25
+ If you find a bug or have a feature suggestion, open an issue on the relevant module's repository. Include enough detail to reproduce the problem or understand the proposal.
26
+
27
+ ## Test Coverage
28
+
29
+ Every commit must include test coverage for the changes it introduces. Retold modules use Mocha in TDD style. Before submitting:
30
+
31
+ - **Write tests** for any new functionality or bug fixes
32
+ - **Run the existing test suite** with `npm test` and confirm all tests pass
33
+ - **Check coverage** with `npm run coverage` if the module supports it
34
+
35
+ Pull requests that break existing tests or lack coverage for new code will not be merged.
36
+
37
+ ## Code Style
38
+
39
+ Follow the conventions of the module you are working in. The general Retold style is:
40
+
41
+ - **Tabs** for indentation, never spaces
42
+ - **Plain JavaScript** only (no TypeScript)
43
+ - **Allman-style braces** (opening brace on its own line)
44
+ - **Variable naming:** `pVariable` for parameters, `tmpVariable` for temporaries, `libSomething` for imports
45
+
46
+ When in doubt, match what the surrounding code does.
47
+
48
+ ## Repository Structure
49
+
50
+ Each module is its own git repository. The [retold](https://github.com/stevenvelozo/retold) repository tracks module organization but does not contain module source code. Direct your pull request to the specific module repository where your change belongs.
package/README.md CHANGED
@@ -1,3 +1,118 @@
1
- # Restify Orator Service Server
1
+ # Orator ServiceServer Restify
2
2
 
3
- Restify abstraction for Orator. Needs more documentation. Feeling brave? You can `npm i` and `node debug/Harness.js` and it will serve up a silly test endpoint.
3
+ > Production HTTP service server for Orator, powered by Restify
4
+
5
+ This is the Restify implementation of the Orator service server interface. It wraps [Restify](https://restify.com/) to provide a full-featured HTTP API server with body parsing, middleware, and all standard HTTP verbs. When you need a real network-facing API server, this is the module you reach for.
6
+
7
+ ## Features
8
+
9
+ - **Full HTTP Support** - All standard HTTP verbs (GET, POST, PUT, DELETE, PATCH, OPTIONS, HEAD)
10
+ - **Restify Middleware** - Both `use` (post-routing) and `pre` (pre-routing) middleware support
11
+ - **Body Parsing** - Built-in Restify body parser with multipart support
12
+ - **Configurable** - Restify server options passed through from Fable settings
13
+ - **Fable Service Provider** - Registers as `OratorServiceServer` in the Fable service manager
14
+
15
+ ## Quick Start
16
+
17
+ ```javascript
18
+ const libFable = require('fable');
19
+ const libOrator = require('orator');
20
+ const libOratorServiceServerRestify = require('orator-serviceserver-restify');
21
+
22
+ const _Fable = new libFable({
23
+ Product: 'MyAPIServer',
24
+ ProductVersion: '1.0.0',
25
+ ServicePort: 8080
26
+ });
27
+
28
+ _Fable.serviceManager.addServiceType('Orator', libOrator);
29
+ _Fable.serviceManager.addServiceType('OratorServiceServer', libOratorServiceServerRestify);
30
+ _Fable.serviceManager.instantiateServiceProvider('Orator');
31
+ _Fable.serviceManager.instantiateServiceProvider('OratorServiceServer');
32
+
33
+ // Register routes
34
+ _Fable.Orator.serviceServer.get('/api/status',
35
+ (pRequest, pResponse, fNext) =>
36
+ {
37
+ pResponse.send({ status: 'ok' });
38
+ return fNext();
39
+ });
40
+
41
+ _Fable.Orator.serviceServer.postWithBodyParser('/api/items',
42
+ (pRequest, pResponse, fNext) =>
43
+ {
44
+ pResponse.send({ created: true, item: pRequest.body });
45
+ return fNext();
46
+ });
47
+
48
+ // Start the server
49
+ _Fable.Orator.startService();
50
+ ```
51
+
52
+ ## Installation
53
+
54
+ ```bash
55
+ npm install orator-serviceserver-restify
56
+ ```
57
+
58
+ ## Configuration
59
+
60
+ Restify-specific configuration is passed through the `RestifyConfiguration` setting:
61
+
62
+ ```javascript
63
+ const _Fable = new libFable({
64
+ ServicePort: 8080,
65
+ RestifyConfiguration: {
66
+ strictNext: true
67
+ }
68
+ });
69
+ ```
70
+
71
+ | Setting | Type | Default | Description |
72
+ |---------|------|---------|-------------|
73
+ | `RestifyConfiguration` | object | `{}` | Options passed to `restify.createServer()` |
74
+ | `RestifyConfiguration.maxParamLength` | number | `Number.MAX_SAFE_INTEGER` | Maximum URL parameter length |
75
+
76
+ ## Middleware
77
+
78
+ The Restify server supports two types of middleware:
79
+
80
+ ```javascript
81
+ const tmpServiceServer = _Fable.Orator.serviceServer;
82
+
83
+ // Post-routing middleware (runs after route matching)
84
+ tmpServiceServer.use(
85
+ (pRequest, pResponse, fNext) =>
86
+ {
87
+ return fNext();
88
+ });
89
+
90
+ // Pre-routing middleware (runs before route matching)
91
+ tmpServiceServer.pre(
92
+ (pRequest, pResponse, fNext) =>
93
+ {
94
+ return fNext();
95
+ });
96
+ ```
97
+
98
+ ## Documentation
99
+
100
+ Full documentation is available in the [`docs`](./docs) folder, or served locally:
101
+
102
+ ```bash
103
+ npx docsify-cli serve docs
104
+ ```
105
+
106
+ ## Related Packages
107
+
108
+ - [orator](https://github.com/stevenvelozo/orator) - API server abstraction
109
+ - [orator-serviceserver-base](https://github.com/stevenvelozo/orator-serviceserver-base) - Abstract service server base class
110
+ - [fable](https://github.com/stevenvelozo/fable) - Application services framework
111
+
112
+ ## License
113
+
114
+ MIT
115
+
116
+ ## Contributing
117
+
118
+ Pull requests are welcome. For details on our code of conduct, contribution process, and testing requirements, see the [Retold Contributing Guide](https://github.com/stevenvelozo/retold/blob/main/docs/contributing.md).
package/docs/.nojekyll ADDED
File without changes
package/docs/README.md ADDED
@@ -0,0 +1,74 @@
1
+ # Orator ServiceServer Restify
2
+
3
+ > Production HTTP service server for Orator, powered by Restify
4
+
5
+ This is the Restify implementation of the Orator service server interface. It wraps [Restify](https://restify.com/) to provide a production-ready HTTP API server. The module extends `orator-serviceserver-base`, overriding the `do*` methods to delegate route registration directly to the underlying Restify server instance.
6
+
7
+ ## Features
8
+
9
+ - **Full HTTP Support** - All standard HTTP verbs (GET, POST, PUT, DELETE, PATCH, OPTIONS, HEAD)
10
+ - **Restify Middleware** - Both `use` (post-routing) and `pre` (pre-routing) middleware support
11
+ - **Body Parsing** - Built-in Restify body parser with multipart support
12
+ - **Configurable** - Restify server options passed through from Fable settings
13
+ - **Fable Service Provider** - Registers as `OratorServiceServer` in the Fable service manager
14
+
15
+ ## Quick Start
16
+
17
+ ```javascript
18
+ const libFable = require('fable');
19
+ const libOrator = require('orator');
20
+ const libOratorServiceServerRestify = require('orator-serviceserver-restify');
21
+
22
+ const _Fable = new libFable({
23
+ Product: 'MyAPIServer',
24
+ ProductVersion: '1.0.0',
25
+ ServicePort: 8080
26
+ });
27
+
28
+ _Fable.serviceManager.addServiceType('Orator', libOrator);
29
+ _Fable.serviceManager.addServiceType('OratorServiceServer', libOratorServiceServerRestify);
30
+ _Fable.serviceManager.instantiateServiceProvider('Orator');
31
+ _Fable.serviceManager.instantiateServiceProvider('OratorServiceServer');
32
+
33
+ _Fable.Orator.serviceServer.get('/api/hello',
34
+ (pRequest, pResponse, fNext) =>
35
+ {
36
+ pResponse.send({ message: 'Hello from Restify!' });
37
+ return fNext();
38
+ });
39
+
40
+ _Fable.Orator.startService();
41
+ ```
42
+
43
+ ## Installation
44
+
45
+ ```bash
46
+ npm install orator-serviceserver-restify
47
+ ```
48
+
49
+ ## How It Works
50
+
51
+ The Restify service server creates a Restify server instance in its constructor and delegates all route and middleware registration directly to it:
52
+
53
+ ```
54
+ Orator → serviceServer.get('/path', handler)
55
+ → OratorServiceServerBase.get() [validates route]
56
+ → OratorServiceServerRestify.doGet() [calls this.server.get()]
57
+ → Restify server handles the route
58
+ ```
59
+
60
+ ## Accessing the Raw Restify Server
61
+
62
+ The underlying Restify server instance is available at `serviceServer.server`:
63
+
64
+ ```javascript
65
+ const tmpRestifyServer = _Fable.Orator.serviceServer.server;
66
+ ```
67
+
68
+ This gives you direct access to any Restify-specific features not exposed through the Orator interface.
69
+
70
+ ## Related Packages
71
+
72
+ - [orator](https://github.com/stevenvelozo/orator) - Main Orator service abstraction
73
+ - [orator-serviceserver-base](https://github.com/stevenvelozo/orator-serviceserver-base) - Abstract base class
74
+ - [fable](https://github.com/stevenvelozo/fable) - Service provider framework
@@ -0,0 +1,10 @@
1
+ - Getting Started
2
+
3
+ - [Introduction](/)
4
+ - [Getting Started](getting-started.md)
5
+
6
+ - Reference
7
+
8
+ - [Configuration](configuration.md)
9
+ - [Middleware](middleware.md)
10
+ - [Body Parsing](body-parsing.md)
@@ -0,0 +1,57 @@
1
+ # Body Parsing
2
+
3
+ The Restify service server uses Restify's built-in body parser plugin to parse incoming request bodies. There are two ways to use body parsing: per-route convenience methods and manual registration.
4
+
5
+ ## Per-Route Body Parsing
6
+
7
+ The simplest approach is to use the `*WithBodyParser` convenience methods, which automatically inject the body parser middleware before your route handler:
8
+
9
+ ```javascript
10
+ _Fable.Orator.serviceServer.postWithBodyParser('/api/items',
11
+ (pRequest, pResponse, fNext) =>
12
+ {
13
+ // pRequest.body is already parsed
14
+ let tmpNewItem = pRequest.body;
15
+ pResponse.send({ created: true, item: tmpNewItem });
16
+ return fNext();
17
+ });
18
+
19
+ _Fable.Orator.serviceServer.putWithBodyParser('/api/items/:id',
20
+ (pRequest, pResponse, fNext) =>
21
+ {
22
+ let tmpUpdatedItem = pRequest.body;
23
+ pResponse.send({ updated: true, item: tmpUpdatedItem });
24
+ return fNext();
25
+ });
26
+ ```
27
+
28
+ Available for all HTTP verbs: `getWithBodyParser`, `postWithBodyParser`, `putWithBodyParser`, `delWithBodyParser`, `patchWithBodyParser`, `optsWithBodyParser`, `headWithBodyParser`.
29
+
30
+ ## Global Body Parsing
31
+
32
+ To parse request bodies for all routes, register the body parser as middleware:
33
+
34
+ ```javascript
35
+ _Fable.Orator.serviceServer.use(_Fable.Orator.serviceServer.bodyParser());
36
+ ```
37
+
38
+ ## Default Body Parser Configuration
39
+
40
+ The Restify body parser is configured with these defaults:
41
+
42
+ | Option | Default | Description |
43
+ |--------|---------|-------------|
44
+ | `maxBodySize` | `0` | Maximum body size (0 = unlimited) |
45
+ | `mapParams` | `false` | Do not map body parameters to `req.params` |
46
+ | `mapFiles` | `false` | Do not map file uploads |
47
+ | `overrideParams` | `false` | Do not override URL params with body params |
48
+ | `multiples` | `true` | Allow multiple file uploads |
49
+ | `hash` | `'sha1'` | Hash algorithm for file uploads |
50
+
51
+ ## Content Types
52
+
53
+ The Restify body parser handles these content types automatically:
54
+
55
+ - `application/json` - Parsed as JSON
56
+ - `application/x-www-form-urlencoded` - Parsed as URL-encoded form data
57
+ - `multipart/form-data` - Parsed as multipart form data (file uploads)
@@ -0,0 +1,61 @@
1
+ # Configuration
2
+
3
+ The Restify service server accepts configuration through Fable settings. Restify-specific options are passed in the `RestifyConfiguration` object.
4
+
5
+ ## Configuration Lookup
6
+
7
+ The module checks for Restify configuration in this order:
8
+
9
+ 1. `options.RestifyConfiguration` (service instantiation options)
10
+ 2. `fable.settings.RestifyConfiguration` (Fable settings)
11
+ 3. Empty object `{}` (default)
12
+
13
+ ## Default Configuration
14
+
15
+ The module sets one default that Restify doesn't:
16
+
17
+ ```javascript
18
+ {
19
+ maxParamLength: Number.MAX_SAFE_INTEGER
20
+ }
21
+ ```
22
+
23
+ This prevents Restify from truncating long URL parameters. Your `RestifyConfiguration` settings are merged on top of this default.
24
+
25
+ ## Configuration Options
26
+
27
+ Any option accepted by `restify.createServer()` can be passed through `RestifyConfiguration`:
28
+
29
+ ```javascript
30
+ const _Fable = new libFable({
31
+ Product: 'MyAPIServer',
32
+ ServicePort: 8080,
33
+ RestifyConfiguration: {
34
+ strictNext: true,
35
+ maxParamLength: 500
36
+ }
37
+ });
38
+ ```
39
+
40
+ | Setting | Type | Default | Description |
41
+ |---------|------|---------|-------------|
42
+ | `maxParamLength` | number | `Number.MAX_SAFE_INTEGER` | Maximum URL parameter length |
43
+ | `strictNext` | boolean | `false` | Require next() to be called in handlers |
44
+ | `name` | string | - | Server name (uses Restify default if not set) |
45
+ | `version` | string | - | API version string |
46
+
47
+ ## Example: JSON Configuration File
48
+
49
+ ```json
50
+ {
51
+ "Product": "MyAPIServer",
52
+ "ProductVersion": "2.0.0",
53
+ "ServicePort": 8080,
54
+ "RestifyConfiguration": {
55
+ "strictNext": true
56
+ },
57
+ "LogStreams": [
58
+ { "level": "info" }
59
+ ]
60
+ }
61
+ ```
package/docs/cover.md ADDED
@@ -0,0 +1,11 @@
1
+ # Orator ServiceServer Restify <small>2</small>
2
+
3
+ > Production HTTP service server for Orator, powered by Restify
4
+
5
+ - Full HTTP verb support with route handler chaining
6
+ - Restify pre and post-routing middleware
7
+ - Built-in body parser with multipart support
8
+ - Seamless integration with the Orator service lifecycle
9
+
10
+ [GitHub](https://github.com/stevenvelozo/orator-serviceserver-restify)
11
+ [Get Started](#orator-serviceserver-restify)
@@ -0,0 +1,73 @@
1
+ /* ============================================================================
2
+ Pict Docuserve - Base Styles
3
+ ============================================================================ */
4
+
5
+ /* Reset and base */
6
+ *, *::before, *::after {
7
+ box-sizing: border-box;
8
+ }
9
+
10
+ html, body {
11
+ margin: 0;
12
+ padding: 0;
13
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
14
+ font-size: 16px;
15
+ line-height: 1.5;
16
+ color: #423D37;
17
+ background-color: #fff;
18
+ -webkit-font-smoothing: antialiased;
19
+ -moz-osx-font-smoothing: grayscale;
20
+ }
21
+
22
+ /* Typography */
23
+ h1, h2, h3, h4, h5, h6 {
24
+ margin-top: 0;
25
+ line-height: 1.3;
26
+ }
27
+
28
+ a {
29
+ color: #2E7D74;
30
+ text-decoration: none;
31
+ }
32
+
33
+ a:hover {
34
+ color: #256861;
35
+ }
36
+
37
+ /* Application container */
38
+ #Docuserve-Application-Container {
39
+ min-height: 100vh;
40
+ }
41
+
42
+ /* Utility: scrollbar styling */
43
+ ::-webkit-scrollbar {
44
+ width: 8px;
45
+ }
46
+
47
+ ::-webkit-scrollbar-track {
48
+ background: #F5F0E8;
49
+ }
50
+
51
+ ::-webkit-scrollbar-thumb {
52
+ background: #D4CCBE;
53
+ border-radius: 4px;
54
+ }
55
+
56
+ ::-webkit-scrollbar-thumb:hover {
57
+ background: #B5AA9A;
58
+ }
59
+
60
+ /* Responsive adjustments */
61
+ @media (max-width: 768px) {
62
+ html {
63
+ font-size: 14px;
64
+ }
65
+
66
+ #Docuserve-Sidebar-Container {
67
+ display: none;
68
+ }
69
+
70
+ .docuserve-body {
71
+ flex-direction: column;
72
+ }
73
+ }
@@ -0,0 +1,106 @@
1
+ # Getting Started
2
+
3
+ ## Installation
4
+
5
+ ```bash
6
+ npm install fable orator orator-serviceserver-restify
7
+ ```
8
+
9
+ ## Setup
10
+
11
+ The Restify service server is registered with Fable as the `OratorServiceServer` service type. Orator will use it automatically once it's instantiated:
12
+
13
+ ```javascript
14
+ const libFable = require('fable');
15
+ const libOrator = require('orator');
16
+ const libOratorServiceServerRestify = require('orator-serviceserver-restify');
17
+
18
+ const _Fable = new libFable({
19
+ Product: 'MyAPIServer',
20
+ ProductVersion: '1.0.0',
21
+ ServicePort: 8080
22
+ });
23
+
24
+ // Register service types
25
+ _Fable.serviceManager.addServiceType('Orator', libOrator);
26
+ _Fable.serviceManager.addServiceType('OratorServiceServer', libOratorServiceServerRestify);
27
+
28
+ // Instantiate (order doesn't matter -- Orator finds the service server during initialization)
29
+ _Fable.serviceManager.instantiateServiceProvider('Orator');
30
+ _Fable.serviceManager.instantiateServiceProvider('OratorServiceServer');
31
+ ```
32
+
33
+ ## Defining Routes
34
+
35
+ Register route handlers on the service server using standard HTTP verb methods:
36
+
37
+ ```javascript
38
+ const tmpServiceServer = _Fable.Orator.serviceServer;
39
+
40
+ // GET request
41
+ tmpServiceServer.get('/api/items',
42
+ (pRequest, pResponse, fNext) =>
43
+ {
44
+ pResponse.send([{ id: 1, name: 'Item One' }]);
45
+ return fNext();
46
+ });
47
+
48
+ // GET with URL parameters
49
+ tmpServiceServer.get('/api/items/:id',
50
+ (pRequest, pResponse, fNext) =>
51
+ {
52
+ pResponse.send({ id: pRequest.params.id });
53
+ return fNext();
54
+ });
55
+
56
+ // POST with body parsing
57
+ tmpServiceServer.postWithBodyParser('/api/items',
58
+ (pRequest, pResponse, fNext) =>
59
+ {
60
+ let tmpNewItem = pRequest.body;
61
+ pResponse.send({ created: true, item: tmpNewItem });
62
+ return fNext();
63
+ });
64
+
65
+ // PUT with body parsing
66
+ tmpServiceServer.putWithBodyParser('/api/items/:id',
67
+ (pRequest, pResponse, fNext) =>
68
+ {
69
+ pResponse.send({ updated: true, id: pRequest.params.id });
70
+ return fNext();
71
+ });
72
+
73
+ // DELETE
74
+ tmpServiceServer.del('/api/items/:id',
75
+ (pRequest, pResponse, fNext) =>
76
+ {
77
+ pResponse.send({ deleted: true });
78
+ return fNext();
79
+ });
80
+ ```
81
+
82
+ ## Starting the Server
83
+
84
+ ```javascript
85
+ _Fable.Orator.startService(
86
+ () =>
87
+ {
88
+ _Fable.log.info('Server is ready');
89
+ });
90
+ ```
91
+
92
+ ## Stopping the Server
93
+
94
+ ```javascript
95
+ _Fable.Orator.stopService(
96
+ () =>
97
+ {
98
+ _Fable.log.info('Server stopped');
99
+ });
100
+ ```
101
+
102
+ ## Next Steps
103
+
104
+ - [Configuration](configuration.md) - Customize the Restify server
105
+ - [Middleware](middleware.md) - Add request processing middleware
106
+ - [Body Parsing](body-parsing.md) - Configure request body parsing
@@ -0,0 +1,39 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
7
+ <meta name="description" content="Documentation powered by pict-docuserve">
8
+
9
+ <title>Documentation</title>
10
+
11
+ <!-- Application Stylesheet -->
12
+ <link href="css/docuserve.css" rel="stylesheet">
13
+ <!-- KaTeX stylesheet for LaTeX equation rendering -->
14
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/katex.min.css">
15
+ <!-- PICT Dynamic View CSS Container -->
16
+ <style id="PICT-CSS"></style>
17
+
18
+ <!-- Load the PICT library from jsDelivr CDN -->
19
+ <script src="https://cdn.jsdelivr.net/npm/pict@1/dist/pict.min.js" type="text/javascript"></script>
20
+ <!-- Bootstrap the Application -->
21
+ <script type="text/javascript">
22
+ //<![CDATA[
23
+ Pict.safeOnDocumentReady(() => { Pict.safeLoadPictApplication(PictDocuserve, 2)});
24
+ //]]>
25
+ </script>
26
+ </head>
27
+ <body>
28
+ <!-- The root container for the Pict application -->
29
+ <div id="Docuserve-Application-Container"></div>
30
+
31
+ <!-- Mermaid diagram rendering -->
32
+ <script src="https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js"></script>
33
+ <script>mermaid.initialize({ startOnLoad: false, theme: 'default' });</script>
34
+ <!-- KaTeX for LaTeX equation rendering -->
35
+ <script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/katex.min.js"></script>
36
+ <!-- Load the Docuserve PICT Application Bundle from jsDelivr CDN -->
37
+ <script src="https://cdn.jsdelivr.net/npm/pict-docuserve@0/dist/pict-docuserve.min.js" type="text/javascript"></script>
38
+ </body>
39
+ </html>
@@ -0,0 +1,79 @@
1
+ # Middleware
2
+
3
+ The Restify service server supports two types of middleware, matching Restify's own middleware pipeline.
4
+
5
+ ## Post-Routing Middleware (use)
6
+
7
+ Middleware registered with `use()` runs after the route has been matched but before the route handler executes:
8
+
9
+ ```javascript
10
+ _Fable.Orator.serviceServer.use(
11
+ (pRequest, pResponse, fNext) =>
12
+ {
13
+ _Fable.log.trace(`${pRequest.method} ${pRequest.url}`);
14
+ return fNext();
15
+ });
16
+ ```
17
+
18
+ This is the standard middleware pattern. The base class validates that the parameter is a function, then the Restify implementation passes it to the underlying Restify server's `use()` method.
19
+
20
+ ## Pre-Routing Middleware (pre)
21
+
22
+ Middleware registered with `pre()` runs before the route is even matched. This is useful for things like request sanitization, CORS headers, or URL rewriting:
23
+
24
+ ```javascript
25
+ _Fable.Orator.serviceServer.pre(
26
+ (pRequest, pResponse, fNext) =>
27
+ {
28
+ // Runs before routing
29
+ return fNext();
30
+ });
31
+ ```
32
+
33
+ ## Middleware Order
34
+
35
+ ```
36
+ Incoming Request
37
+
38
+ pre() middleware (before routing)
39
+
40
+ Route Matching
41
+
42
+ use() middleware (after routing)
43
+
44
+ Route Handler(s)
45
+
46
+ Response
47
+ ```
48
+
49
+ ## Example: Request Logging
50
+
51
+ ```javascript
52
+ _Fable.Orator.serviceServer.use(
53
+ (pRequest, pResponse, fNext) =>
54
+ {
55
+ let tmpStartTime = Date.now();
56
+
57
+ pResponse.on('finish',
58
+ () =>
59
+ {
60
+ let tmpDuration = Date.now() - tmpStartTime;
61
+ _Fable.log.info(`${pRequest.method} ${pRequest.url} ${pResponse.statusCode} ${tmpDuration}ms`);
62
+ });
63
+
64
+ return fNext();
65
+ });
66
+ ```
67
+
68
+ ## Example: CORS Headers
69
+
70
+ ```javascript
71
+ _Fable.Orator.serviceServer.pre(
72
+ (pRequest, pResponse, fNext) =>
73
+ {
74
+ pResponse.header('Access-Control-Allow-Origin', '*');
75
+ pResponse.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS');
76
+ pResponse.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
77
+ return fNext();
78
+ });
79
+ ```