Skip to content

Commit 3716ec0

Browse files
documentation: improve helpers
1 parent 580c7e5 commit 3716ec0

File tree

6 files changed

+211
-24
lines changed

6 files changed

+211
-24
lines changed

docs/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ The REserve server object implements an interface that mimics the [EventEmitter:
3636

3737
## Helpers
3838

39-
REserve also offers some helpers to simplify implementations :
39+
REserve offers some helpers to simplify implementations :
4040
* [`log`](log.md) to handle and output server logs
4141
* [`body`](body.md) to read a request body
4242
* [`send`](send.md) to build a response
@@ -45,7 +45,7 @@ REserve also offers some helpers to simplify implementations :
4545

4646
## Mocking
4747

48-
REserve includes a [mocking environment](mocking.md) to **simplify the tests**. It takes the **configuration** and asynchronously returns a server object **augmented with a `request` method** to simulate incoming requests.
48+
REserve includes a [mocking environment](mocking.md) to **ease the tests**. It takes the **configuration** and returns a fake server object **augmented with a `request` method** to simulate incoming requests.
4949

5050
## Version history
5151

docs/body.md

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# `body` helper
22

3+
REserve offers a method to **deserialize a request body**.
4+
35
```typescript
46
interface BodyOptions {
57
ignoreContentLength?: boolean
@@ -14,22 +16,28 @@ type BodyResult = Promise<Buffer | string | object> & {
1416
function body (request: IncomingMessage, options?: BodyOptions): BodyResult
1517
```
1618

17-
REserve offers a **basic** method to **deserialize the request body**.
19+
> Types definition for `body`
1820

1921
```javascript
20-
const { body } = require('reserve')
22+
import { body }from 'reserve'
2123
2224
async function customHandler (request, response) {
2325
const requestBody = await body(request).json()
2426
/* ... */
2527
}
2628
```
2729

28-
Depending on the request's `content-type` *(if set)*, `body()` will automatically return :
29-
* a string when `text/plain`
30-
* an object when `application/json`
31-
* a [Buffer]() otherwise
30+
> Example of `body`
31+
32+
If the `content-type` is specified in the request headers and starts with :
33+
* `text/plain` : a `string` is returned
34+
* `application/json` : an `object` is returned _(after applying [`JSON.parse`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse) on the request content)_.
35+
* Otherwise, a [`Buffer`](https://nodejs.org/docs/latest/api/buffer.html) is returned
36+
37+
It is possible to force the return type using :
3238

33-
**NOTE** : even if the `content-type` is specified, the caller may decide to use `.buffer()`, `.text()` or `.json()`.
39+
* `await body(request).text()` : a `string` is returned
40+
* `await body(request).json()` : an `object` is returned
41+
* `await body(request).buffer()` : a [`Buffer`](https://nodejs.org/docs/latest/api/buffer.html) is returned
3442

35-
**NOTE** : if the request's `content-length` is set (and not ignored), the buffer is allocated accordingly meaning the result might be truncated (if too small) or padded with `\x00` (if too large).
43+
**NOTE** : if the request's `content-length` is set (and not ignored), the buffer is allocated accordingly meaning the result might be truncated *(if too small)* or padded with `\x00` *(if too large)*.

docs/capture.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
# `capture` helper
22

3+
REserve offers a mechanism to **capture the response stream** and **duplicate its content** to another **writable stream**.
4+
35
```typescript
46
function capture (response: ServerResponse, stream: WritableStream): Promise<void>
57
```
68

7-
REserve offers a mechanism to **capture the response stream** and **duplicate its content** to another **writable stream**.
9+
> Types definition for `capture`
810

911
**NOTE** : The content is decoded if the [`content-encoding`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding) header contains: `gzip`, `deflate` or `br` *(only one, no combination is supported)*.
1012

@@ -36,3 +38,4 @@ mappings: [{
3638
}]
3739
```
3840

41+
> Example of `capture` used to cache resources

docs/events.md

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,12 @@ When a **request is processed**, the following diagram illustrates the **sequenc
1212

1313
| Event<br>`eventName`| Parameters<br>_`...members`_ | Description |
1414
|---|---|---|
15-
| `'created'` | `server`[`http.server`](https://nodejs.org/api/http.html#http_class_http_server) \| [`https.server`](https://nodejs.org/api/https.html#https_class_https_server)<br>`configuration`[`IConfiguration`](iconfiguration.md) | Only available to `listeners`, this event is emitted **after** the HTTP(S) server is `'created'` and **before** it accepts requests.
16-
| `'ready'` | `url``string`<br>`port``number`<br>`http2``boolean` | The server is listening and **ready** to receive requests.<br>`url` contains a valid address *(for instance: `'http://192.168.4.1:8080/'`)*.
17-
| `'incoming'` | `method``string` *(uppercase)*<br>`incomingUrl``String`<br>`url``string`<br>`headers``{ [key: string]: string \| string[] }`<br>`start``Date`<br>`id``number`<br>`internal``boolean` | **New** request received.<br>`incomingUrl` contains the original URL *(before normalization)*.<br>`url` contains the URL to be matched.<br>`id` is a unique identifier allocated by REserve.<br>`internal` signals internally dispatched request *(see [configuration interface](iconfiguration.md#async-dispatch-request-response)*).<br><br><small>These members are also available for `'error'`, `'redirecting'`,`'redirected'`, `'aborted'` and `'closed'` events.</small>|
18-
| `'error'` | `reason``any` | An error occurred. |
19-
| `'error'` | `...'incoming'`<br>`reason``any` | An error occurred while processing a request. |
20-
| `'redirecting'` | `...'incoming'`<br>`type``string`<br>`redirect``string` \| `number` | Processing redirection to handler, gives handler type and redirection value. <br />*For instance, when a request will be served by the [file handler](#file), this event is generated once. But if the requested resource does not exist, the request will be redirected to the [status](#status) 404 triggering again this event.* |
21-
22-
| `'redirected'` | *same parameters as `'incoming'`*`end` *(Date)*<br>`timeSpent` *(Number of ms)*<br>`statusCode` *(Number)*</li></ul> | Request is fully processed. `timeSpent` is evaluated by comparing `start` and `end` (i.e. not using high resolution timers) and provided for information only. |
23-
| `'aborted'` | *same parameters as `'incoming'`* | Request was [aborted](https://nodejs.org/api/http.html#http_event_aborted).<small><br />Added in version 1.9.0</small> |
24-
| `'closed'` | *same parameters as `'incoming'`* | Request underlying connection was [closed](https://nodejs.org/api/http.html#http_event_close_2). <small><br />Added in version 1.9.0</small>|
15+
| `'created'` | `server`: [`http.server`](https://nodejs.org/api/http.html#http_class_http_server) \| [`https.server`](https://nodejs.org/api/https.html#https_class_https_server)<br>`configuration`: [`IConfiguration`](iconfiguration.md) | Only available to `listeners`, this event is emitted **after** the HTTP(S) server is `'created'` and **before** it accepts requests.
16+
| `'ready'` | `url``string`<br>`port``number`<br>`http2``boolean` | The server is listening and **ready** to receive requests.<br>`url` contains a valid address *(for instance: `'http://192.168.4.1:8080/'`)*.
17+
| `'incoming'` | `method``string` *(uppercase)*<br>`incomingUrl``String`<br>`url``string`<br>`headers``{ [key: string]: string \| string[] }`<br>`start``Date`<br>`id``number`<br>`internal`: `boolean` | **New** request received.<br>`incomingUrl` contains the original URL *(before normalization)*.<br>`url` contains the URL to be matched.<br>`id` is a unique identifier allocated by REserve.<br>`internal` signals internally dispatched request *(see [configuration interface](iconfiguration.md#async-dispatch-request-response)*).<br><br><small>These members are also available for `'error'`, `'redirecting'`,`'redirected'`, `'aborted'` and `'closed'` events.</small>|
18+
| `'error'` | `reason``any` | An **error** occurred. |
19+
| `'error'` | `...'incoming'`<br>`reason``any` | An **error** occurred while **processing** a request. |
20+
| `'redirecting'` | `...'incoming'`<br>`type``string`<br>`redirect``string` \| `number` | Request will be **processed** by a handler.<br>`type` contains the handler prefix.<br>`redirect` contains the redirection value. |
21+
| `'redirected'` | `...'incoming'`<br>`end``Date`<br>`timeSpent``number` *(ms)*<br>`statusCode``number` | Request is **fully** processed.<br>`timeSpent` is evaluated by comparing `start` and `end` *(not a high resolution timer)*. |
22+
| `'aborted'` | `...'incoming'` | Request was **[aborted](https://nodejs.org/api/http.html#http_event_aborted)**. |
23+
| `'closed'` | `...'incoming'` | Request was **[closed](https://nodejs.org/api/http.html#http_event_close_2)**. |

docs/log.md

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
# `log` helper
2+
3+
REserve offers a method to **output server events** in the standard console.
4+
5+
```typescript
6+
function log (server: Server, verbose?: boolean): Server
7+
```
8+
9+
> Types definition for `log`
10+
11+
```javascript
12+
import { log, read, serve } from 'reserve'
13+
14+
read('reserve.json')
15+
.then(configuration => log(serve(configuration)))
16+
```
17+
18+
> Example of `log`
19+
20+
The helper supports two modes based on the `verbose` parameter :
21+
22+
* When `verbose` is `false` : only a summary is generated when a request is **completed**. It includes `method`, `url` *(initial)*, `statusCode` and `timeSpent`.
23+
24+
```text
25+
Server running at http://192.168.4.41:8080/
26+
SERVE GET / 200 12 ms
27+
SERVE GET /load-ui5.js 200 4 ms
28+
SERVE GET /init.js 200 3 ms
29+
SERVE GET /test/MockServer.js 200 3 ms
30+
SERVE GET /const.js 200 3 ms
31+
SERVE GET /test/newItem.js 200 3 ms
32+
SERVE GET /manifest.json 200 2 ms
33+
SERVE GET /model/metadata.xml 200 2 ms
34+
SERVE GET /model/metadata.xml 200 3 ms
35+
SERVE GET /model/AppConfigurationSet.json 200 3 ms
36+
SERVE GET /model/TodoItemSet.json 200 2 ms
37+
SERVE GET /Component-preload.js 404 2 ms
38+
SERVE GET /Component-preload.js 404 1 ms
39+
SERVE GET /Component.js 200 2 ms
40+
SERVE GET /manifest.json 200 2 ms
41+
SERVE GET /favicon.ico 404 1 ms
42+
SERVE GET /css/styles.css 200 6 ms
43+
SERVE GET /i18n/i18n_fr.properties 404 2 ms
44+
SERVE GET /i18n/i18n_en.properties 404 1 ms
45+
SERVE GET /i18n/i18n.properties 200 2 ms
46+
SERVE GET /view/App.view.xml 200 2 ms
47+
SERVE GET /controller/App.controller.js 200 2 ms
48+
```
49+
50+
> Example of `log(...,false)` output
51+
52+
In case of error, a trace with error information is generated
53+
54+
```text
55+
ERROR GET /i18n/i18n_fr.properties
56+
\____ Error: FAILED
57+
```
58+
59+
> Example of error
60+
61+
* When `verbose` is `true` : all request events are dumped, the request `id` is used to **correlate** the traces.
62+
* `INCMG` : `incoming` event, documents `method` and `url`
63+
* `RDRCT` : `redirecting` event, documents `type` and `redirect`
64+
* `SERVE` : `redirected` event, documents `statusCode` and `timeSpent`
65+
* `ABORT` : `aborted` event
66+
* `CLOSE` : `closed` event
67+
68+
```text
69+
Server running at http://192.168.4.41:8080/
70+
INCMG 0001 GET /
71+
RDRCT 0001 file ./webapp/index.html
72+
CLOSE 0001
73+
SERVE 0001 200 16 ms
74+
INCMG 0002 GET /load-ui5.js
75+
RDRCT 0002 file ./webapp/load-ui5.js
76+
CLOSE 0002
77+
SERVE 0002 200 5 ms
78+
INCMG 0003 GET /init.js
79+
RDRCT 0003 file ./webapp/init.js
80+
CLOSE 0003
81+
SERVE 0003 200 4 ms
82+
INCMG 0004 GET /test/MockServer.js
83+
RDRCT 0004 file ./webapp/test/MockServer.js
84+
CLOSE 0004
85+
SERVE 0004 200 4 ms
86+
INCMG 0005 GET /const.js
87+
RDRCT 0005 file ./webapp/const.js
88+
INCMG 0006 GET /test/newItem.js
89+
RDRCT 0006 file ./webapp/test/newItem.js
90+
CLOSE 0005
91+
SERVE 0005 200 5 ms
92+
CLOSE 0006
93+
SERVE 0006 200 5 ms
94+
INCMG 0007 GET /manifest.json
95+
RDRCT 0007 file ./webapp/manifest.json
96+
CLOSE 0007
97+
SERVE 0007 200 3 ms
98+
INCMG 0008 GET /model/metadata.xml
99+
RDRCT 0008 file ./webapp/model/metadata.xml
100+
CLOSE 0008
101+
SERVE 0008 200 3 ms
102+
INCMG 0009 GET /model/metadata.xml
103+
RDRCT 0009 file ./webapp/model/metadata.xml
104+
CLOSE 0009
105+
SERVE 0009 200 3 ms
106+
INCMG 000A GET /model/AppConfigurationSet.json
107+
RDRCT 000A file ./webapp/model/AppConfigurationSet.json
108+
CLOSE 000A
109+
SERVE 000A 200 4 ms
110+
INCMG 000B GET /model/TodoItemSet.json
111+
RDRCT 000B file ./webapp/model/TodoItemSet.json
112+
CLOSE 000B
113+
SERVE 000B 200 3 ms
114+
INCMG 000C GET /Component-preload.js
115+
RDRCT 000C file ./webapp/Component-preload.js
116+
RDRCT 000C status 404
117+
SERVE 000C 404 3 ms
118+
CLOSE 000C
119+
INCMG 000D GET /Component-preload.js
120+
RDRCT 000D file ./webapp/Component-preload.js
121+
RDRCT 000D status 404
122+
SERVE 000D 404 2 ms
123+
CLOSE 000D
124+
INCMG 000E GET /Component.js
125+
RDRCT 000E file ./webapp/Component.js
126+
CLOSE 000E
127+
SERVE 000E 200 3 ms
128+
INCMG 000F GET /manifest.json
129+
RDRCT 000F file ./webapp/manifest.json
130+
CLOSE 000F
131+
SERVE 000F 200 5 ms
132+
INCMG 0010 GET /css/styles.css
133+
RDRCT 0010 file ./webapp/css/styles.css
134+
CLOSE 0010
135+
SERVE 0010 200 4 ms
136+
INCMG 0011 GET /i18n/i18n_fr.properties
137+
RDRCT 0011 file ./webapp/i18n/i18n_fr.properties
138+
RDRCT 0011 status 404
139+
SERVE 0011 404 2 ms
140+
CLOSE 0011
141+
INCMG 0012 GET /i18n/i18n_en.properties
142+
RDRCT 0012 file ./webapp/i18n/i18n_en.properties
143+
RDRCT 0012 status 404
144+
SERVE 0012 404 2 ms
145+
CLOSE 0012
146+
INCMG 0013 GET /i18n/i18n.properties
147+
RDRCT 0013 file ./webapp/i18n/i18n.properties
148+
CLOSE 0013
149+
SERVE 0013 200 3 ms
150+
INCMG 0014 GET /view/App.view.xml
151+
RDRCT 0014 file ./webapp/view/App.view.xml
152+
CLOSE 0014
153+
SERVE 0014 200 3 ms
154+
INCMG 0015 GET /controller/App.controller.js
155+
RDRCT 0015 file ./webapp/controller/App.controller.js
156+
CLOSE 0015
157+
SERVE 0015 200 3 ms
158+
```
159+
160+
> Example of `log(...,true)` output
161+
162+
In case of error, a trace with error information is generated
163+
164+
```text
165+
INCMG 0011 GET /i18n/i18n_fr.properties
166+
RDRCT 0011 file ./webapp/i18n/i18n_fr.properties
167+
RDRCT 0011 custom ./error.js
168+
ERROR 0011 Error: FAILED
169+
RDRCT 0011 status 500
170+
SERVE 0011 500 3 ms
171+
CLOSE 0011
172+
```
173+
174+
> Example of error

docs/send.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# `send` helper
22

3+
REserve offers a way to **build** responses : `statusCode` and `headers` *may* be specified, `noBody` prevents the body sending.
4+
35
```typescript
46
interface SendOptions {
57
statusCode?: number /* defaulted to 200 */
@@ -11,12 +13,13 @@ function send (response: ServerResponse, data: ReadableStream, options?: SendOpt
1113
function send (response: ServerResponse, data?: string | object, options?: SendOptions): void
1214
```
1315

14-
REserve offers a way to easily build responses : `statusCode` and `headers` can be specified, `noBody` prevents the body sending.
16+
> Types definition for `send`
1517

1618
Headers are defaulted *(if not set)* depending on the `data` type :
1719
* `string` :
1820
* `content-type` is set to `text/plain`
19-
* `content-length` is set computed a text encoder
21+
* `content-length` is calculated based on the UTF-8 encoding byte length
2022
* `object` :
2123
* `content-type` is set to `application/json`
22-
* `content-length` is set using a text encoder
24+
* `content-length` is calculated based on the UTF-8 encoding byte length
25+
* `ReadableStream` : not set

0 commit comments

Comments
 (0)