@wooksjs/event-http 0.2.8 → 0.2.10
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/README.md +2 -535
- package/dist/index.cjs +14 -13
- package/dist/index.d.ts +84 -18
- package/dist/index.mjs +11 -11
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -48,539 +48,6 @@ app.on('GET', 'hello/:name', () => `Hello ${ useRouteParams().get('name') }!`)
|
|
|
48
48
|
app.listen(3000, () => { console.log('Wooks Server is up on port 3000') })
|
|
49
49
|
```
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
You can create http(s) server manually and pass server callback from the wooks http app:
|
|
51
|
+
## Documentation
|
|
53
52
|
|
|
54
|
-
|
|
55
|
-
import { useRouteParams } from 'wooks'
|
|
56
|
-
import { createHttpApp } from '@wooksjs/event-http'
|
|
57
|
-
import http from 'http' // or https
|
|
58
|
-
|
|
59
|
-
const app = createHttpApp()
|
|
60
|
-
|
|
61
|
-
app.get('hello/:name', () => `Hello ${ useRouteParams().get('name') }!`)
|
|
62
|
-
|
|
63
|
-
const server = http.createServer(app.getServerCb())
|
|
64
|
-
server.listen(3000, () => { console.log('Wooks Server is up on port 3000') })
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
## Quick Navigation
|
|
68
|
-
- [User Documentation](./README.md#User-Documentation)
|
|
69
|
-
- [URL Parameters](./README.md#)
|
|
70
|
-
- [Query Parameters](./README.md#Query-Parameters)
|
|
71
|
-
---
|
|
72
|
-
- [Request](./README.md#Request)
|
|
73
|
-
- [Request Method and Headers](./README.md#Request-Method-and-Headers)
|
|
74
|
-
- [Request Cookies](./README.md#Request-Cookies)
|
|
75
|
-
- [Request Authorization](./README.md#Request-Authorization)
|
|
76
|
-
- [Request Body Parser](./README.md#Request-Body-Parser)
|
|
77
|
-
---
|
|
78
|
-
- [Response](./README.md#Response)
|
|
79
|
-
- [Response Headers](./README.md#Response-Headers)
|
|
80
|
-
- [Response Cookies](./README.md#Response-Cookies)
|
|
81
|
-
- [Response Status](./README.md#Response-Status)
|
|
82
|
-
- [Cache-Control](./README.md#Cache-Control)
|
|
83
|
-
- [Proxy Requests](./README.md#Proxy-Requests)
|
|
84
|
-
- [Serve File](./README.md#Serve-File)
|
|
85
|
-
---
|
|
86
|
-
- [Create you own hooks](./README.md#Create-you-own-hooks)
|
|
87
|
-
---
|
|
88
|
-
- [Adapter Documentation](./README.md#Adapter-Documentation)
|
|
89
|
-
- [Create a new wooks context](./README.md#Create-a-new-wooks-context)
|
|
90
|
-
- [Create a responder](./README.md#Create-a-responder)
|
|
91
|
-
- [Restore Context](./README.md#Restore-Context)
|
|
92
|
-
|
|
93
|
-
## User Documentation
|
|
94
|
-
|
|
95
|
-
### URL Parameters
|
|
96
|
-
To get access to URL parameters use composable function `useRouteParams`
|
|
97
|
-
|
|
98
|
-
```js
|
|
99
|
-
import { useRouteParams } from 'wooks'
|
|
100
|
-
app.get('parametric/:param1/:param2/...', () => {
|
|
101
|
-
const { params, get } = useRouteParams()
|
|
102
|
-
// presume we had a request on `/parametric/value1/value2`
|
|
103
|
-
console.log('param1=' + get('param1'))
|
|
104
|
-
// prints "param1=value1"
|
|
105
|
-
console.log('param2=' + get('param2'))
|
|
106
|
-
// prints "param2=value2"
|
|
107
|
-
console.log(params)
|
|
108
|
-
// prints {
|
|
109
|
-
// param1: "value1",
|
|
110
|
-
// param2: "value2"
|
|
111
|
-
// }
|
|
112
|
-
})
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
### Query Parameters
|
|
116
|
-
To get access to Query parameters use composable function `useSearchParams`
|
|
117
|
-
|
|
118
|
-
```js
|
|
119
|
-
import { useSearchParams } from '@wooksjs/event-http'
|
|
120
|
-
app.get('with-query', () => {
|
|
121
|
-
const { jsonSearchParams, urlSearchParams } = useSearchParams()
|
|
122
|
-
// presume we had a request on `/with-query?param1=abc¶m2=cde`
|
|
123
|
-
console.log('param1=' + urlSearchParams('param1'))
|
|
124
|
-
// prints "param1=abc"
|
|
125
|
-
console.log('param2=' + urlSearchParams('param2'))
|
|
126
|
-
// prints "param1=cde"
|
|
127
|
-
console.log(jsonSearchParams)
|
|
128
|
-
// prints {
|
|
129
|
-
// param1: "abc",
|
|
130
|
-
// param2: "cde"
|
|
131
|
-
// }
|
|
132
|
-
})
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
### Request
|
|
136
|
-
To get a reference to the raw request instance use composable function `useRequest`
|
|
137
|
-
|
|
138
|
-
You probably don't need a `rawRequest` unless you are developing some new feature. All the base use-cases covered with other composable functions.
|
|
139
|
-
|
|
140
|
-
```js
|
|
141
|
-
import { useRequest } from '@wooksjs/event-http'
|
|
142
|
-
app.get('test', () => {
|
|
143
|
-
const { rawRequest } = useRequest()
|
|
144
|
-
})
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
### Request Method and Headers
|
|
148
|
-
`useRequest` provides some more shortcuts for useful data
|
|
149
|
-
|
|
150
|
-
```js
|
|
151
|
-
import { useRequest } from '@wooksjs/event-http'
|
|
152
|
-
app.get('test', async () => {
|
|
153
|
-
const {
|
|
154
|
-
url, // request url (string)
|
|
155
|
-
method, // request method (string)
|
|
156
|
-
headers, // request headers (object)
|
|
157
|
-
rawBody, // request body ((): Promise<Buffer>)
|
|
158
|
-
} = useRequest()
|
|
159
|
-
|
|
160
|
-
const body = await rawBody() // body as a Buffer
|
|
161
|
-
})
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
### Request Cookies
|
|
165
|
-
Cookies are not parsed unless requested. Composable function `useCookies` provides cookie getter and raw cookies string.
|
|
166
|
-
|
|
167
|
-
```js
|
|
168
|
-
import { useCookies } from '@wooksjs/event-http'
|
|
169
|
-
app.get('test', async () => {
|
|
170
|
-
const {
|
|
171
|
-
rawCookies, // "cookie" from headers (string | undefined)
|
|
172
|
-
getCookie, // cookie getter ((name): string | null)
|
|
173
|
-
} = useCookies()
|
|
174
|
-
|
|
175
|
-
console.log(getCookie('session'))
|
|
176
|
-
// prints the value of the cookie with the name "session"
|
|
177
|
-
})
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
### Request Authorization
|
|
181
|
-
`useAuthorization` function provides useful helpers for auth-headers:
|
|
182
|
-
|
|
183
|
-
```js
|
|
184
|
-
import { useAuthorization } from '@wooksjs/event-http'
|
|
185
|
-
app.get('test', async () => {
|
|
186
|
-
const {
|
|
187
|
-
authorization, // the raw value of "authorization" header : string
|
|
188
|
-
authType, // the auth type (Bearer/Basic) : string
|
|
189
|
-
authRawCredentials, // the auth credentials that follow auth type : string
|
|
190
|
-
isBasic, // true if authType === 'Basic' : () => boolean
|
|
191
|
-
isBearer, // true if authType === 'Bearer' : () => boolean
|
|
192
|
-
basicCredentials, // parsed basic auth credentials : () => { username: string, password: string }
|
|
193
|
-
} = useAuthorization()
|
|
194
|
-
|
|
195
|
-
if (isBasic()) {
|
|
196
|
-
const { username, password } = basicCredentials()
|
|
197
|
-
console.log({ username, password })
|
|
198
|
-
} else if (isBearer()) {
|
|
199
|
-
const token = authRawCredentials
|
|
200
|
-
console.log({ token })
|
|
201
|
-
} else {
|
|
202
|
-
// unknown or empty authorization header
|
|
203
|
-
}
|
|
204
|
-
})
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
### Request Body Parser
|
|
208
|
-
[More details here](https://github.com/wooksjs/body#readme)
|
|
209
|
-
|
|
210
|
-
### Response
|
|
211
|
-
The easiest way to respond to the request is to return some value from handler function like this:
|
|
212
|
-
```js
|
|
213
|
-
app.get('string_response', () => {
|
|
214
|
-
return 'hello world!'
|
|
215
|
-
// responds with:
|
|
216
|
-
// 200
|
|
217
|
-
// Content-Length: ...
|
|
218
|
-
// Content-Type: text/plain
|
|
219
|
-
// hello world!
|
|
220
|
-
})
|
|
221
|
-
```
|
|
222
|
-
|
|
223
|
-
Whatever is returned from the handler is the response. `Content-Type` and `Content-Length` headers will be calculated accordingly.
|
|
224
|
-
|
|
225
|
-
If a handler returns a json object, it will be stringified and the header `Content-Type` will be set to `application/json` automatically:
|
|
226
|
-
```js
|
|
227
|
-
app.get('json_response', () => {
|
|
228
|
-
return { value: 'hello world!' }
|
|
229
|
-
// responds with:
|
|
230
|
-
// 200
|
|
231
|
-
// Content-Length: ...
|
|
232
|
-
// Content-Type: application/json
|
|
233
|
-
// { "value": "hello world!" }
|
|
234
|
-
})
|
|
235
|
-
```
|
|
236
|
-
|
|
237
|
-
**Supported response types:**
|
|
238
|
-
1. string (text/plain, text/html, application/xml - depending on the content)
|
|
239
|
-
2. object/array (application/json)
|
|
240
|
-
3. boolean (text/plain)
|
|
241
|
-
4. readable stream (you must specify `Content-Type` and `Content-Length` headers yourself)
|
|
242
|
-
5. fetch (native) response (streaming body to client response)
|
|
243
|
-
|
|
244
|
-
**Raw Response**: When it is needed to take the full control of the response, use composable function `useResponse`
|
|
245
|
-
|
|
246
|
-
When you get a raw response instance you take away the control of the response on yourself. The framework will not process the output of the handler in this case.
|
|
247
|
-
|
|
248
|
-
An example of using raw response instance:
|
|
249
|
-
```js
|
|
250
|
-
import { useResponse } from '@wooksjs/event-http'
|
|
251
|
-
app.get('test', () => {
|
|
252
|
-
const { rawResponse } = useResponse()
|
|
253
|
-
const res = rawResponse()
|
|
254
|
-
res.writeHead(200, {})
|
|
255
|
-
res.end('ok')
|
|
256
|
-
})
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
If you don't want to take away a responsibility for the response but still need a raw response instance you can use `{ passthrough: true }` as an argument.
|
|
260
|
-
The next example does the same thing as the previous example using `passthrough` options:
|
|
261
|
-
|
|
262
|
-
```js
|
|
263
|
-
import { useResponse } from '@wooksjs/event-http'
|
|
264
|
-
app.get('test', () => {
|
|
265
|
-
const { rawResponse } = useResponse()
|
|
266
|
-
const res = rawResponse({ passthrough: true })
|
|
267
|
-
return 'ok'
|
|
268
|
-
})
|
|
269
|
-
```
|
|
270
|
-
|
|
271
|
-
### Response Headers
|
|
272
|
-
A function `useSetHeaders` provides variety of response headers helpers:
|
|
273
|
-
|
|
274
|
-
```js
|
|
275
|
-
import { useSetHeaders, contentTypes } from '@wooksjs/event-http'
|
|
276
|
-
app.get('test', async () => {
|
|
277
|
-
const {
|
|
278
|
-
setHeader, //sets header: (name: string, value: string | number) => void;
|
|
279
|
-
removeHeader, //removes header: (name: string) => void;
|
|
280
|
-
setContentType, //sets "Content-Type": (value: string) => void;
|
|
281
|
-
headers, //Object with response headers: Record<string, string>;
|
|
282
|
-
enableCors, //sets "Access-Control-Allow-Origin": (origin?: string) => void;
|
|
283
|
-
} = useSetHeaders()
|
|
284
|
-
|
|
285
|
-
setContentType(contentTypes.application.json)
|
|
286
|
-
setHeader('server', 'myServer v1.0')
|
|
287
|
-
enableCors()
|
|
288
|
-
return '{ "value": "OK" }'
|
|
289
|
-
})
|
|
290
|
-
```
|
|
291
|
-
|
|
292
|
-
Another hook for set header
|
|
293
|
-
|
|
294
|
-
```js
|
|
295
|
-
import { useSetHeader } from '@wooksjs/event-http'
|
|
296
|
-
app.get('test', async () => {
|
|
297
|
-
const server = useSetHeader('server')
|
|
298
|
-
server.value = 'myServer v1.0'
|
|
299
|
-
})
|
|
300
|
-
```
|
|
301
|
-
|
|
302
|
-
### Response Cookies
|
|
303
|
-
A function `useSetCookies` provides variety of set-cookie helpers:
|
|
304
|
-
|
|
305
|
-
```js
|
|
306
|
-
import { useSetCookies } from '@wooksjs/event-http'
|
|
307
|
-
app.get('test', async () => {
|
|
308
|
-
const {
|
|
309
|
-
setCookie, // sets cookie : (name: string, value: string, attrs?) => void;
|
|
310
|
-
removeCookie, // removes cookie from setlist : (name: string) => void;
|
|
311
|
-
clearCookies, // removes all the cookies from setlist : () => void;
|
|
312
|
-
cookies, // returns a value of Set-Cookie header: () => string[];
|
|
313
|
-
} = useSetCookies()
|
|
314
|
-
|
|
315
|
-
setCookie('session', 'value', {
|
|
316
|
-
expires: '2029-01-01', // Date | string | number;
|
|
317
|
-
maxAge: '1h', // number | TProstoTimeMultiString;
|
|
318
|
-
domain: 'my-domain', // string;
|
|
319
|
-
path: '/home', // string;
|
|
320
|
-
secure: true, // boolean;
|
|
321
|
-
httpOnly: false, // boolean;
|
|
322
|
-
sameSite: true, // boolean | 'Lax' | 'None' | 'Strict';
|
|
323
|
-
})
|
|
324
|
-
})
|
|
325
|
-
```
|
|
326
|
-
|
|
327
|
-
Another hook for set-cookie
|
|
328
|
-
|
|
329
|
-
```js
|
|
330
|
-
import { useSetCookie } from '@wooksjs/event-http'
|
|
331
|
-
app.get('test', async () => {
|
|
332
|
-
const session = useSetCookie('session')
|
|
333
|
-
session.value = 'value'
|
|
334
|
-
session.attrs = {
|
|
335
|
-
expires: '2029-01-01', // Date | string | number;
|
|
336
|
-
maxAge: '1h', // number | TProstoTimeMultiString;
|
|
337
|
-
domain: 'my-domain', // string;
|
|
338
|
-
path: '/home', // string;
|
|
339
|
-
secure: true, // boolean;
|
|
340
|
-
httpOnly: false, // boolean;
|
|
341
|
-
sameSite: true, // boolean | 'Lax' | 'None' | 'Strict';
|
|
342
|
-
}
|
|
343
|
-
})
|
|
344
|
-
```
|
|
345
|
-
|
|
346
|
-
### Response Status
|
|
347
|
-
It's possible to control the response status via `status` function that is available in `useResponse()`
|
|
348
|
-
|
|
349
|
-
```js
|
|
350
|
-
import { useResponse } from '@wooksjs/event-http'
|
|
351
|
-
app.get('test', async () => {
|
|
352
|
-
const { status } = useResponse()
|
|
353
|
-
|
|
354
|
-
// use function calls:
|
|
355
|
-
status(201) // sets status 201 for the response
|
|
356
|
-
|
|
357
|
-
console.log(status()) // when called with no argument returns the status
|
|
358
|
-
|
|
359
|
-
// also possible to use value:
|
|
360
|
-
// status.value = 201
|
|
361
|
-
// console.log(status.value)
|
|
362
|
-
|
|
363
|
-
return 'response with status 201'
|
|
364
|
-
})
|
|
365
|
-
```
|
|
366
|
-
|
|
367
|
-
### Cache-Control
|
|
368
|
-
`useSetCacheControl` function provides helpers for headers responsible for cache control
|
|
369
|
-
|
|
370
|
-
```js
|
|
371
|
-
import { useSetCacheControl } from '@wooksjs/event-http'
|
|
372
|
-
app.get('static/*', () => {
|
|
373
|
-
const {
|
|
374
|
-
setAge, // sets Age (v: number | TProstoTimeMultiString) => void
|
|
375
|
-
setExpires, // sets Expires (v: Date | string | number) => void
|
|
376
|
-
setPragmaNoCache, // sets Pragma: no-cache (v: boolean) => void
|
|
377
|
-
setCacheControl, // sets Cache-Control (data: TCacheControl) => void
|
|
378
|
-
} = useSetCacheControl()
|
|
379
|
-
|
|
380
|
-
setAge('2h 15m')
|
|
381
|
-
setExpires('2022-05-05')
|
|
382
|
-
setCacheControl({
|
|
383
|
-
mustRevalidate: true,
|
|
384
|
-
noCache: false,
|
|
385
|
-
noStore: false,
|
|
386
|
-
noTransform: true,
|
|
387
|
-
public: true,
|
|
388
|
-
private: 'field',
|
|
389
|
-
proxyRevalidate: true,
|
|
390
|
-
maxAge: '3h 30m 12s',
|
|
391
|
-
sMaxage: '2h 27m 54s',
|
|
392
|
-
})
|
|
393
|
-
})
|
|
394
|
-
```
|
|
395
|
-
|
|
396
|
-
### Proxy Requests
|
|
397
|
-
[More details here](https://github.com/wooksjs/proxy#readme)
|
|
398
|
-
|
|
399
|
-
### Serve File
|
|
400
|
-
[More details here](https://github.com/wooksjs/serve-file#readme)
|
|
401
|
-
|
|
402
|
-
## Create you own hooks
|
|
403
|
-
|
|
404
|
-
As an example we'll create a composable that resolves user profile
|
|
405
|
-
|
|
406
|
-
```ts
|
|
407
|
-
import { useAuthorization, useHttpContext } from '@wooksjs/event-http'
|
|
408
|
-
|
|
409
|
-
interface TUser {
|
|
410
|
-
username: string
|
|
411
|
-
age: number
|
|
412
|
-
// ...
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
export function useUserProfile() {
|
|
416
|
-
// 1. get custom-typed context
|
|
417
|
-
const { store } = useHttpContext<{ user: TUser }>()
|
|
418
|
-
const user = store('user')
|
|
419
|
-
|
|
420
|
-
// 2. in this example will use basic credentials approach to get user name
|
|
421
|
-
const { basicCredentials } = useAuthorization()
|
|
422
|
-
|
|
423
|
-
// 3. get user name
|
|
424
|
-
const username = basicCredentials()?.username
|
|
425
|
-
|
|
426
|
-
// 4. user data async loader
|
|
427
|
-
async function userProfile() {
|
|
428
|
-
// first check if user data was already cached
|
|
429
|
-
// for this request
|
|
430
|
-
if (!user.value) {
|
|
431
|
-
// no user data cached yet, try to read user
|
|
432
|
-
// and return the result
|
|
433
|
-
user.value = await readUser()
|
|
434
|
-
}
|
|
435
|
-
// return user profile from cache
|
|
436
|
-
return user.value
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
// abstract readUser function
|
|
440
|
-
function readUser(): Promise<TUser> {
|
|
441
|
-
// return db.readUser(username)
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
return {
|
|
445
|
-
username, // we have user name syncronously
|
|
446
|
-
userProfile, // and userProfile as (() => Promise<TUser>)
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
// example of usage of our useUserProfile
|
|
451
|
-
app.get('/user', async () => {
|
|
452
|
-
const { username, userProfile } = useUserProfile()
|
|
453
|
-
console.log('username =', username)
|
|
454
|
-
const data = await userProfile()
|
|
455
|
-
return { user: data }
|
|
456
|
-
})
|
|
457
|
-
```
|
|
458
|
-
|
|
459
|
-
Example of custom set header hook
|
|
460
|
-
|
|
461
|
-
```ts
|
|
462
|
-
import { useSetHeaders } from '@wooksjs/event-http'
|
|
463
|
-
import { attachHook } from '@wooksjs/event-core'
|
|
464
|
-
|
|
465
|
-
function useHeaderHook(name: string) {
|
|
466
|
-
const { setHeader, headers } = useSetHeaders()
|
|
467
|
-
|
|
468
|
-
return attachHook({
|
|
469
|
-
name,
|
|
470
|
-
type: 'header',
|
|
471
|
-
}, {
|
|
472
|
-
get: () => headers()[name] as string,
|
|
473
|
-
set: (value: string | number) => setHeader(name, value),
|
|
474
|
-
})
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
// usage
|
|
478
|
-
|
|
479
|
-
app.get('/test', () => {
|
|
480
|
-
const myHeader = useHeaderHook('x-my-header')
|
|
481
|
-
myHeader.value = 'header value'
|
|
482
|
-
// *Please note that useSetHeader('x-my-header') will work similarly*
|
|
483
|
-
return 'ok'
|
|
484
|
-
})
|
|
485
|
-
|
|
486
|
-
// result:
|
|
487
|
-
// 200
|
|
488
|
-
// headers:
|
|
489
|
-
// x-my-header: header value
|
|
490
|
-
```
|
|
491
|
-
|
|
492
|
-
## Adapter Documentation
|
|
493
|
-
|
|
494
|
-
The next paragraph is for those who wants to create threir own adapter and get more control over the wooks.
|
|
495
|
-
|
|
496
|
-
### Create a new wooks context
|
|
497
|
-
|
|
498
|
-
Wooks context is a special object that stores:
|
|
499
|
-
1. **instance of request** - is used to get data from request
|
|
500
|
-
2. **instance of response** - is used to send a response
|
|
501
|
-
3. **parsed route params** - usually Web App frameworks put it to `req` (`req.params`)
|
|
502
|
-
4. **cache store** - is used to cache alread computed values, e.g. parsed body, parsed cookies, ..., in order to avoid multiple parsing/computetaion of the same entities.
|
|
503
|
-
|
|
504
|
-
When request is generated by the client a new Wooks context must be created.
|
|
505
|
-
|
|
506
|
-
`const {restoreCtx, clearCtx} = createHttpContext({ req, res })`
|
|
507
|
-
|
|
508
|
-
```ts
|
|
509
|
-
import { createHttpContext } from '@wooksjs/event-http'
|
|
510
|
-
|
|
511
|
-
function requestHandler(req, res) {
|
|
512
|
-
const {
|
|
513
|
-
// restoreCtx hook helps to restore wooks context
|
|
514
|
-
// after any async operatuon
|
|
515
|
-
restoreCtx,
|
|
516
|
-
|
|
517
|
-
// clearCtx hook helps to clear wooks context
|
|
518
|
-
// when the request is already processed
|
|
519
|
-
clearCtx,
|
|
520
|
-
|
|
521
|
-
// store hook to access wooks store of the current ctx
|
|
522
|
-
store,
|
|
523
|
-
} = createHttpContext({
|
|
524
|
-
// request instance
|
|
525
|
-
req,
|
|
526
|
-
// response instance
|
|
527
|
-
res,
|
|
528
|
-
})
|
|
529
|
-
|
|
530
|
-
// if req already contains parsed params (req.params)
|
|
531
|
-
// then those will be picked up automatically
|
|
532
|
-
// unless you overwrite it here
|
|
533
|
-
store('routeParams').value = { name: 'value' }
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
```
|
|
537
|
-
|
|
538
|
-
### Create a responder
|
|
539
|
-
|
|
540
|
-
Responder is a function that takes any output of the request handler and transforms it into http response, processing headers, cookies, formats etc.
|
|
541
|
-
|
|
542
|
-
`const {createResponse, respond} = createWooksResponder()`
|
|
543
|
-
|
|
544
|
-
```ts
|
|
545
|
-
import { createWooksResponder, createHttpContext } from '@wooksjs/event-http'
|
|
546
|
-
|
|
547
|
-
const {createResponse, respond} = createWooksResponder(
|
|
548
|
-
/*renderer, // (optional) instance of TWooksResponseRenderer*/
|
|
549
|
-
/*errorRenderer, // (optional) instance of TWooksResponseRenderer*/
|
|
550
|
-
)
|
|
551
|
-
|
|
552
|
-
async function requestHandler(req, res) {
|
|
553
|
-
// 1. create wooks context
|
|
554
|
-
const {restoreCtx, clearCtx} = createHttpContext({ req, res })
|
|
555
|
-
// 2. process request based on routers/handlers and get the output
|
|
556
|
-
const response = await createHttpContext()
|
|
557
|
-
// 3. restore wooks context
|
|
558
|
-
restoreCtx()
|
|
559
|
-
// 4. respond
|
|
560
|
-
respond(response)
|
|
561
|
-
// 5. clear wooks context
|
|
562
|
-
clearCtx()
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
async function processHandlers() {
|
|
566
|
-
// routing, processing, handling, ...
|
|
567
|
-
}
|
|
568
|
-
|
|
569
|
-
```
|
|
570
|
-
|
|
571
|
-
### Restore Context
|
|
572
|
-
|
|
573
|
-
There is one more way to get `restoreCtx` hook besides the one you get when `createHttpContext`
|
|
574
|
-
|
|
575
|
-
`const { restoreCtx, clearCtx } = useHttpContext()`
|
|
576
|
-
|
|
577
|
-
```ts
|
|
578
|
-
import { useHttpContext } from '@wooksjs/event-http'
|
|
579
|
-
|
|
580
|
-
async function someHandler() {
|
|
581
|
-
const { restoreCtx, clearCtx } = useHttpContext()
|
|
582
|
-
await ... // some async operations
|
|
583
|
-
restoreCtx()
|
|
584
|
-
// here the wooks context is back
|
|
585
|
-
}
|
|
586
|
-
```
|
|
53
|
+
To check out docs, visit [wooksjs.org](https://wooksjs.org/).
|
package/dist/index.cjs
CHANGED
|
@@ -464,7 +464,7 @@ function __asyncValues(o) {
|
|
|
464
464
|
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
|
465
465
|
}
|
|
466
466
|
|
|
467
|
-
class
|
|
467
|
+
class BaseHttpResponseRenderer {
|
|
468
468
|
render(response) {
|
|
469
469
|
if (typeof response.body === 'string' || typeof response.body === 'boolean' || typeof response.body === 'number') {
|
|
470
470
|
if (!response.getContentType())
|
|
@@ -625,8 +625,8 @@ const defaultStatus = {
|
|
|
625
625
|
PATCH: exports.EHttpStatusCode.Accepted,
|
|
626
626
|
DELETE: exports.EHttpStatusCode.Accepted,
|
|
627
627
|
};
|
|
628
|
-
const baseRenderer = new
|
|
629
|
-
class
|
|
628
|
+
const baseRenderer = new BaseHttpResponseRenderer();
|
|
629
|
+
class BaseHttpResponse {
|
|
630
630
|
constructor(renderer = baseRenderer) {
|
|
631
631
|
this.renderer = renderer;
|
|
632
632
|
this._status = 0;
|
|
@@ -803,7 +803,7 @@ const preStyles = 'font-family: monospace;'
|
|
|
803
803
|
+ 'border-radius: 8px;'
|
|
804
804
|
+ 'background-color: #494949;'
|
|
805
805
|
+ 'box-shadow: 0px 0px 3px 2px rgb(255 255 255 / 20%);';
|
|
806
|
-
class
|
|
806
|
+
class HttpErrorRenderer extends BaseHttpResponseRenderer {
|
|
807
807
|
renderHtml(response) {
|
|
808
808
|
const data = response.body || {};
|
|
809
809
|
response.setContentType('text/html');
|
|
@@ -812,7 +812,7 @@ class WooksErrorRenderer extends BaseWooksResponseRenderer {
|
|
|
812
812
|
`<head><title>${data.statusCode} ${httpStatusCodes[data.statusCode]}</title></head>` +
|
|
813
813
|
`<body><center><h1>${data.statusCode} ${httpStatusCodes[data.statusCode]}</h1></center>` +
|
|
814
814
|
`<center><h4>${data.message}</h1></center><hr color="#666">` +
|
|
815
|
-
`<center style="color: #666;"> Wooks v${"0.2.
|
|
815
|
+
`<center style="color: #666;"> Wooks v${"0.2.10"} </center>` +
|
|
816
816
|
`${keys.length ? `<pre style="${preStyles}">${JSON.stringify(Object.assign(Object.assign({}, data), { statusCode: undefined, message: undefined, error: undefined }), null, ' ')}</pre>` : ''}` +
|
|
817
817
|
'</body></html>';
|
|
818
818
|
}
|
|
@@ -877,15 +877,15 @@ class HttpError extends Error {
|
|
|
877
877
|
|
|
878
878
|
function createWooksResponder(
|
|
879
879
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
880
|
-
renderer = new
|
|
880
|
+
renderer = new BaseHttpResponseRenderer(),
|
|
881
881
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
882
|
-
errorRenderer = new
|
|
882
|
+
errorRenderer = new HttpErrorRenderer()) {
|
|
883
883
|
function createResponse(data) {
|
|
884
884
|
const { hasResponded } = useResponse();
|
|
885
885
|
if (hasResponded())
|
|
886
886
|
return null;
|
|
887
887
|
if (data instanceof Error) {
|
|
888
|
-
const r = new
|
|
888
|
+
const r = new BaseHttpResponse(errorRenderer);
|
|
889
889
|
let httpError;
|
|
890
890
|
if (data instanceof HttpError) {
|
|
891
891
|
httpError = data;
|
|
@@ -896,11 +896,11 @@ errorRenderer = new WooksErrorRenderer()) {
|
|
|
896
896
|
r.setBody(httpError.body);
|
|
897
897
|
return r;
|
|
898
898
|
}
|
|
899
|
-
else if (data instanceof
|
|
899
|
+
else if (data instanceof BaseHttpResponse) {
|
|
900
900
|
return data;
|
|
901
901
|
}
|
|
902
902
|
else {
|
|
903
|
-
return new
|
|
903
|
+
return new BaseHttpResponse(renderer).setBody(data);
|
|
904
904
|
}
|
|
905
905
|
}
|
|
906
906
|
return {
|
|
@@ -1026,15 +1026,16 @@ function createHttpApp(opts, wooks) {
|
|
|
1026
1026
|
return new WooksHttp(opts, wooks);
|
|
1027
1027
|
}
|
|
1028
1028
|
|
|
1029
|
-
exports.
|
|
1030
|
-
exports.
|
|
1029
|
+
exports.BaseHttpResponse = BaseHttpResponse;
|
|
1030
|
+
exports.BaseHttpResponseRenderer = BaseHttpResponseRenderer;
|
|
1031
1031
|
exports.HttpError = HttpError;
|
|
1032
|
-
exports.
|
|
1032
|
+
exports.HttpErrorRenderer = HttpErrorRenderer;
|
|
1033
1033
|
exports.WooksHttp = WooksHttp;
|
|
1034
1034
|
exports.WooksURLSearchParams = WooksURLSearchParams;
|
|
1035
1035
|
exports.createHttpApp = createHttpApp;
|
|
1036
1036
|
exports.createHttpContext = createHttpContext;
|
|
1037
1037
|
exports.createWooksResponder = createWooksResponder;
|
|
1038
|
+
exports.httpStatusCodes = httpStatusCodes;
|
|
1038
1039
|
exports.renderCacheControl = renderCacheControl;
|
|
1039
1040
|
exports.useAccept = useAccept;
|
|
1040
1041
|
exports.useAuthorization = useAuthorization;
|
package/dist/index.d.ts
CHANGED
|
@@ -13,9 +13,9 @@ import { URLSearchParams as URLSearchParams_2 } from 'url';
|
|
|
13
13
|
import { Wooks } from 'wooks';
|
|
14
14
|
import { WooksAdapterBase } from 'wooks';
|
|
15
15
|
|
|
16
|
-
export declare class
|
|
17
|
-
protected renderer:
|
|
18
|
-
constructor(renderer?:
|
|
16
|
+
export declare class BaseHttpResponse<BodyType = unknown> {
|
|
17
|
+
protected renderer: BaseHttpResponseRenderer;
|
|
18
|
+
constructor(renderer?: BaseHttpResponseRenderer);
|
|
19
19
|
protected _status: EHttpStatusCode;
|
|
20
20
|
protected _body?: BodyType;
|
|
21
21
|
protected _headers: Record<string, string | string[]>;
|
|
@@ -39,8 +39,8 @@ export declare class BaseWooksResponse<BodyType = unknown> {
|
|
|
39
39
|
respond(): Promise<unknown>;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
export declare class
|
|
43
|
-
render(response:
|
|
42
|
+
export declare class BaseHttpResponseRenderer<T = unknown> implements TWooksResponseRenderer<T> {
|
|
43
|
+
render(response: BaseHttpResponse<T>): string | Uint8Array;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
export declare function createHttpApp(opts?: TWooksHttpOptions, wooks?: Wooks | WooksAdapterBase): WooksHttp;
|
|
@@ -68,7 +68,7 @@ export declare function createHttpContext(data: THttpEventData): {
|
|
|
68
68
|
};
|
|
69
69
|
|
|
70
70
|
export declare function createWooksResponder(renderer?: TWooksResponseRenderer<any>, errorRenderer?: TWooksResponseRenderer<any>): {
|
|
71
|
-
createResponse: <T = unknown>(data: T) =>
|
|
71
|
+
createResponse: <T = unknown>(data: T) => BaseHttpResponse<TWooksErrorBodyExt | T> | null;
|
|
72
72
|
respond: (data: unknown) => Promise<unknown> | undefined;
|
|
73
73
|
};
|
|
74
74
|
|
|
@@ -143,11 +143,84 @@ export declare class HttpError<T extends TWooksErrorBody = TWooksErrorBody> exte
|
|
|
143
143
|
protected _body: string | T;
|
|
144
144
|
constructor(code?: THttpErrorCodes, _body?: string | T);
|
|
145
145
|
get body(): TWooksErrorBodyExt;
|
|
146
|
-
protected renderer?:
|
|
147
|
-
attachRenderer(renderer:
|
|
148
|
-
getRenderer():
|
|
146
|
+
protected renderer?: HttpErrorRenderer;
|
|
147
|
+
attachRenderer(renderer: HttpErrorRenderer): void;
|
|
148
|
+
getRenderer(): HttpErrorRenderer | undefined;
|
|
149
149
|
}
|
|
150
150
|
|
|
151
|
+
export declare class HttpErrorRenderer extends BaseHttpResponseRenderer<TWooksErrorBodyExt> {
|
|
152
|
+
renderHtml(response: BaseHttpResponse<TWooksErrorBodyExt>): string;
|
|
153
|
+
renderText(response: BaseHttpResponse<TWooksErrorBodyExt>): string;
|
|
154
|
+
renderJson(response: BaseHttpResponse<TWooksErrorBodyExt>): string;
|
|
155
|
+
render(response: BaseHttpResponse<TWooksErrorBodyExt>): string;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export declare const httpStatusCodes: {
|
|
159
|
+
100: string;
|
|
160
|
+
101: string;
|
|
161
|
+
102: string;
|
|
162
|
+
103: string;
|
|
163
|
+
200: string;
|
|
164
|
+
201: string;
|
|
165
|
+
202: string;
|
|
166
|
+
203: string;
|
|
167
|
+
204: string;
|
|
168
|
+
205: string;
|
|
169
|
+
206: string;
|
|
170
|
+
207: string;
|
|
171
|
+
208: string;
|
|
172
|
+
226: string;
|
|
173
|
+
300: string;
|
|
174
|
+
301: string;
|
|
175
|
+
302: string;
|
|
176
|
+
303: string;
|
|
177
|
+
304: string;
|
|
178
|
+
305: string;
|
|
179
|
+
306: string;
|
|
180
|
+
307: string;
|
|
181
|
+
308: string;
|
|
182
|
+
400: string;
|
|
183
|
+
401: string;
|
|
184
|
+
402: string;
|
|
185
|
+
403: string;
|
|
186
|
+
404: string;
|
|
187
|
+
405: string;
|
|
188
|
+
406: string;
|
|
189
|
+
407: string;
|
|
190
|
+
408: string;
|
|
191
|
+
409: string;
|
|
192
|
+
410: string;
|
|
193
|
+
411: string;
|
|
194
|
+
412: string;
|
|
195
|
+
413: string;
|
|
196
|
+
414: string;
|
|
197
|
+
415: string;
|
|
198
|
+
416: string;
|
|
199
|
+
417: string;
|
|
200
|
+
418: string;
|
|
201
|
+
421: string;
|
|
202
|
+
422: string;
|
|
203
|
+
423: string;
|
|
204
|
+
424: string;
|
|
205
|
+
425: string;
|
|
206
|
+
426: string;
|
|
207
|
+
428: string;
|
|
208
|
+
429: string;
|
|
209
|
+
431: string;
|
|
210
|
+
451: string;
|
|
211
|
+
500: string;
|
|
212
|
+
501: string;
|
|
213
|
+
502: string;
|
|
214
|
+
503: string;
|
|
215
|
+
504: string;
|
|
216
|
+
505: string;
|
|
217
|
+
506: string;
|
|
218
|
+
507: string;
|
|
219
|
+
508: string;
|
|
220
|
+
510: string;
|
|
221
|
+
511: string;
|
|
222
|
+
};
|
|
223
|
+
|
|
151
224
|
export declare function renderCacheControl(data: TCacheControl): string;
|
|
152
225
|
|
|
153
226
|
export declare type TAuthCache = {
|
|
@@ -273,7 +346,7 @@ export declare interface TWooksHttpOptions {
|
|
|
273
346
|
}
|
|
274
347
|
|
|
275
348
|
export declare interface TWooksResponseRenderer<T = unknown> {
|
|
276
|
-
render: (response:
|
|
349
|
+
render: (response: BaseHttpResponse<T>) => string | Uint8Array;
|
|
277
350
|
}
|
|
278
351
|
|
|
279
352
|
export declare function useAccept(): {
|
|
@@ -405,13 +478,6 @@ export declare function useStatus(): {
|
|
|
405
478
|
isDefined: boolean;
|
|
406
479
|
};
|
|
407
480
|
|
|
408
|
-
export declare class WooksErrorRenderer extends BaseWooksResponseRenderer<TWooksErrorBodyExt> {
|
|
409
|
-
renderHtml(response: BaseWooksResponse<TWooksErrorBodyExt>): string;
|
|
410
|
-
renderText(response: BaseWooksResponse<TWooksErrorBodyExt>): string;
|
|
411
|
-
renderJson(response: BaseWooksResponse<TWooksErrorBodyExt>): string;
|
|
412
|
-
render(response: BaseWooksResponse<TWooksErrorBodyExt>): string;
|
|
413
|
-
}
|
|
414
|
-
|
|
415
481
|
export declare class WooksHttp extends WooksAdapterBase {
|
|
416
482
|
protected opts?: TWooksHttpOptions | undefined;
|
|
417
483
|
constructor(opts?: TWooksHttpOptions | undefined, wooks?: Wooks | WooksAdapterBase);
|
|
@@ -429,7 +495,7 @@ export declare class WooksHttp extends WooksAdapterBase {
|
|
|
429
495
|
getServer(): http.Server<typeof http.IncomingMessage, typeof http.ServerResponse> | undefined;
|
|
430
496
|
attachServer(server?: Server): void;
|
|
431
497
|
protected responder: {
|
|
432
|
-
createResponse: <T = unknown>(data: T) =>
|
|
498
|
+
createResponse: <T = unknown>(data: T) => BaseHttpResponse<T | TWooksErrorBodyExt> | null;
|
|
433
499
|
respond: (data: unknown) => Promise<unknown> | undefined;
|
|
434
500
|
};
|
|
435
501
|
protected respond(data: unknown): void;
|
package/dist/index.mjs
CHANGED
|
@@ -462,7 +462,7 @@ function __asyncValues(o) {
|
|
|
462
462
|
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
|
463
463
|
}
|
|
464
464
|
|
|
465
|
-
class
|
|
465
|
+
class BaseHttpResponseRenderer {
|
|
466
466
|
render(response) {
|
|
467
467
|
if (typeof response.body === 'string' || typeof response.body === 'boolean' || typeof response.body === 'number') {
|
|
468
468
|
if (!response.getContentType())
|
|
@@ -623,8 +623,8 @@ const defaultStatus = {
|
|
|
623
623
|
PATCH: EHttpStatusCode.Accepted,
|
|
624
624
|
DELETE: EHttpStatusCode.Accepted,
|
|
625
625
|
};
|
|
626
|
-
const baseRenderer = new
|
|
627
|
-
class
|
|
626
|
+
const baseRenderer = new BaseHttpResponseRenderer();
|
|
627
|
+
class BaseHttpResponse {
|
|
628
628
|
constructor(renderer = baseRenderer) {
|
|
629
629
|
this.renderer = renderer;
|
|
630
630
|
this._status = 0;
|
|
@@ -801,7 +801,7 @@ const preStyles = 'font-family: monospace;'
|
|
|
801
801
|
+ 'border-radius: 8px;'
|
|
802
802
|
+ 'background-color: #494949;'
|
|
803
803
|
+ 'box-shadow: 0px 0px 3px 2px rgb(255 255 255 / 20%);';
|
|
804
|
-
class
|
|
804
|
+
class HttpErrorRenderer extends BaseHttpResponseRenderer {
|
|
805
805
|
renderHtml(response) {
|
|
806
806
|
const data = response.body || {};
|
|
807
807
|
response.setContentType('text/html');
|
|
@@ -810,7 +810,7 @@ class WooksErrorRenderer extends BaseWooksResponseRenderer {
|
|
|
810
810
|
`<head><title>${data.statusCode} ${httpStatusCodes[data.statusCode]}</title></head>` +
|
|
811
811
|
`<body><center><h1>${data.statusCode} ${httpStatusCodes[data.statusCode]}</h1></center>` +
|
|
812
812
|
`<center><h4>${data.message}</h1></center><hr color="#666">` +
|
|
813
|
-
`<center style="color: #666;"> Wooks v${"0.2.
|
|
813
|
+
`<center style="color: #666;"> Wooks v${"0.2.10"} </center>` +
|
|
814
814
|
`${keys.length ? `<pre style="${preStyles}">${JSON.stringify(Object.assign(Object.assign({}, data), { statusCode: undefined, message: undefined, error: undefined }), null, ' ')}</pre>` : ''}` +
|
|
815
815
|
'</body></html>';
|
|
816
816
|
}
|
|
@@ -875,15 +875,15 @@ class HttpError extends Error {
|
|
|
875
875
|
|
|
876
876
|
function createWooksResponder(
|
|
877
877
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
878
|
-
renderer = new
|
|
878
|
+
renderer = new BaseHttpResponseRenderer(),
|
|
879
879
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
880
|
-
errorRenderer = new
|
|
880
|
+
errorRenderer = new HttpErrorRenderer()) {
|
|
881
881
|
function createResponse(data) {
|
|
882
882
|
const { hasResponded } = useResponse();
|
|
883
883
|
if (hasResponded())
|
|
884
884
|
return null;
|
|
885
885
|
if (data instanceof Error) {
|
|
886
|
-
const r = new
|
|
886
|
+
const r = new BaseHttpResponse(errorRenderer);
|
|
887
887
|
let httpError;
|
|
888
888
|
if (data instanceof HttpError) {
|
|
889
889
|
httpError = data;
|
|
@@ -894,11 +894,11 @@ errorRenderer = new WooksErrorRenderer()) {
|
|
|
894
894
|
r.setBody(httpError.body);
|
|
895
895
|
return r;
|
|
896
896
|
}
|
|
897
|
-
else if (data instanceof
|
|
897
|
+
else if (data instanceof BaseHttpResponse) {
|
|
898
898
|
return data;
|
|
899
899
|
}
|
|
900
900
|
else {
|
|
901
|
-
return new
|
|
901
|
+
return new BaseHttpResponse(renderer).setBody(data);
|
|
902
902
|
}
|
|
903
903
|
}
|
|
904
904
|
return {
|
|
@@ -1024,4 +1024,4 @@ function createHttpApp(opts, wooks) {
|
|
|
1024
1024
|
return new WooksHttp(opts, wooks);
|
|
1025
1025
|
}
|
|
1026
1026
|
|
|
1027
|
-
export {
|
|
1027
|
+
export { BaseHttpResponse, BaseHttpResponseRenderer, EHttpStatusCode, HttpError, HttpErrorRenderer, WooksHttp, WooksURLSearchParams, createHttpApp, createHttpContext, createWooksResponder, httpStatusCodes, renderCacheControl, useAccept, useAuthorization, useCookies, useHeaders, useHttpContext, useRequest, useResponse, useSearchParams, useSetCacheControl, useSetCookie, useSetCookies, useSetHeader, useSetHeaders, useStatus };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wooksjs/event-http",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.10",
|
|
4
4
|
"description": "@wooksjs/event-http",
|
|
5
5
|
"main": "dist/index.cjs",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -31,8 +31,9 @@
|
|
|
31
31
|
"url": "https://github.com/wooksjs/wooksjs/issues"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
|
34
|
-
"wooks": "0.2.
|
|
35
|
-
"@
|
|
34
|
+
"wooks": "0.2.10",
|
|
35
|
+
"@prostojs/router": "^0.0.16",
|
|
36
|
+
"@wooksjs/event-core": "0.2.10"
|
|
36
37
|
},
|
|
37
38
|
"homepage": "https://github.com/wooksjs/wooksjs/tree/main/packages/event-http#readme"
|
|
38
39
|
}
|