wooks 0.0.1-beta.7 → 0.0.1-beta.8
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 -512
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -119,516 +119,6 @@ app.get('with-query', () => {
|
|
|
119
119
|
})
|
|
120
120
|
```
|
|
121
121
|
|
|
122
|
-
##
|
|
122
|
+
## Composables
|
|
123
123
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
You probably don't need a `rawRequest` unless you are developing some new feature. All the base use-cases covered with other composable functions.
|
|
127
|
-
|
|
128
|
-
```js
|
|
129
|
-
import { useRequest } from '@wooksjs/composables'
|
|
130
|
-
app.get('test', () => {
|
|
131
|
-
const { rawRequest } = useRequest()
|
|
132
|
-
})
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
### Request Method, Headers, ...
|
|
136
|
-
|
|
137
|
-
`useRequest` provides some more shortcuts for useful data
|
|
138
|
-
|
|
139
|
-
```js
|
|
140
|
-
import { useRequest } from '@wooksjs/composables'
|
|
141
|
-
app.get('test', async () => {
|
|
142
|
-
const {
|
|
143
|
-
url, // request url (string)
|
|
144
|
-
method, // request method (string)
|
|
145
|
-
headers, // request headers (object)
|
|
146
|
-
rawBody, // request body ((): Promise<Buffer>)
|
|
147
|
-
} = useRequest()
|
|
148
|
-
|
|
149
|
-
const body = await rawBody() // body as a Buffer
|
|
150
|
-
})
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
### Request Cookies
|
|
154
|
-
|
|
155
|
-
Cookies are not parsed unless requested. Composable function `useCookies` provides cookie getter and raw cookies string.
|
|
156
|
-
|
|
157
|
-
```js
|
|
158
|
-
import { useCookies } from '@wooksjs/composables'
|
|
159
|
-
app.get('test', async () => {
|
|
160
|
-
const {
|
|
161
|
-
rawCookies, // "cookie" from headers (string | undefined)
|
|
162
|
-
getCookie, // cookie getter ((name): string | null)
|
|
163
|
-
} = useCookies()
|
|
164
|
-
|
|
165
|
-
console.log(getCookie('session'))
|
|
166
|
-
// prints the value of the cookie with the name "session"
|
|
167
|
-
})
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
### Request Body Parser
|
|
171
|
-
|
|
172
|
-
`npm install @wooksjs/body`
|
|
173
|
-
|
|
174
|
-
Function `useBody` provides utilities for getting decoded and parsed body.
|
|
175
|
-
|
|
176
|
-
Body parser supports json, string, multipart/form-data and application/x-www-form-urlencoded content-types.
|
|
177
|
-
|
|
178
|
-
Body parser does not parse every request's body. The parsing happens only when you call `parseBody` function.
|
|
179
|
-
|
|
180
|
-
The request handler is invoked even before the request body was sent to the server.
|
|
181
|
-
|
|
182
|
-
```js
|
|
183
|
-
import { useBody } from '@wooksjs/body'
|
|
184
|
-
app.post('test', async () => {
|
|
185
|
-
const {
|
|
186
|
-
isJson, // checks if content-type is "application/json" : () => boolean;
|
|
187
|
-
isHtml, // checks if content-type is "text/html" : () => boolean;
|
|
188
|
-
isXml, // checks if content-type is "application/xml" : () => boolean;
|
|
189
|
-
isText, // checks if content-type is "text/plain" : () => boolean;
|
|
190
|
-
isBinary, // checks if content-type is binary : () => boolean;
|
|
191
|
-
isFormData, // checks if content-type is "multipart/form-data" : () => boolean;
|
|
192
|
-
isUrlencoded, // checks if content-type is "application/x-www-form-urlencoded" : () => boolean;
|
|
193
|
-
isCompressed, // checks content-encoding : () => boolean | undefined;
|
|
194
|
-
contentEncodings, // returns an array of encodings : () => string[];
|
|
195
|
-
parseBody, // parses body according to content-type : <T = unknown>() => Promise<T>;
|
|
196
|
-
rawBody, // returns raw body Buffer : () => Promise<Buffer>;
|
|
197
|
-
} = useBody()
|
|
198
|
-
|
|
199
|
-
// the handler got the control, but the body isn't loaded yet
|
|
200
|
-
//...
|
|
201
|
-
|
|
202
|
-
console.log(await parseBody())
|
|
203
|
-
|
|
204
|
-
// after `await parseBody()` the body was loaded and parsed
|
|
205
|
-
// ...
|
|
206
|
-
})
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
### Request Authorization
|
|
210
|
-
|
|
211
|
-
`useAuthorization` function provides useful helpers for auth-headers:
|
|
212
|
-
|
|
213
|
-
```js
|
|
214
|
-
import { useAuthorization } from '@wooksjs/composables'
|
|
215
|
-
app.get('test', async () => {
|
|
216
|
-
const {
|
|
217
|
-
authorization, // the raw value of "authorization" header : string
|
|
218
|
-
authType, // the auth type (Bearer/Basic) : string
|
|
219
|
-
authRawCredentials, // the auth credentials that follow auth type : string
|
|
220
|
-
isBasic, // true if authType === 'Basic' : () => boolean
|
|
221
|
-
isBearer, // true if authType === 'Bearer' : () => boolean
|
|
222
|
-
basicCredentials, // parsed basic auth credentials : () => { username: string, password: string }
|
|
223
|
-
} = useAuthorization()
|
|
224
|
-
|
|
225
|
-
if (isBasic()) {
|
|
226
|
-
const { username, password } = basicCredentials()
|
|
227
|
-
console.log({ username, password })
|
|
228
|
-
} else if (isBearer()) {
|
|
229
|
-
const token = authRawCredentials
|
|
230
|
-
console.log({ token })
|
|
231
|
-
} else {
|
|
232
|
-
// unknown or empty authorization header
|
|
233
|
-
}
|
|
234
|
-
})
|
|
235
|
-
```
|
|
236
|
-
|
|
237
|
-
## Response
|
|
238
|
-
|
|
239
|
-
The easiest way to respond to the request is to return some value from handler function like this:
|
|
240
|
-
```js
|
|
241
|
-
app.get('string_response', () => {
|
|
242
|
-
return 'hello world!'
|
|
243
|
-
// responds with:
|
|
244
|
-
// 200
|
|
245
|
-
// Content-Length: ...
|
|
246
|
-
// Content-Type: text/plain
|
|
247
|
-
// hello world!
|
|
248
|
-
})
|
|
249
|
-
```
|
|
250
|
-
|
|
251
|
-
Whatever is returned from the handler is the response. `Content-Type` and `Content-Length` headers will be calculated accordingly.
|
|
252
|
-
|
|
253
|
-
If a handler returns a json object, it will be stringified and the header `Content-Type` will be set to `application/json` automatically:
|
|
254
|
-
```js
|
|
255
|
-
app.get('json_response', () => {
|
|
256
|
-
return { value: 'hello world!' }
|
|
257
|
-
// responds with:
|
|
258
|
-
// 200
|
|
259
|
-
// Content-Length: ...
|
|
260
|
-
// Content-Type: application/json
|
|
261
|
-
// { "value": "hello world!" }
|
|
262
|
-
})
|
|
263
|
-
```
|
|
264
|
-
|
|
265
|
-
**Supported response types:**
|
|
266
|
-
1. string (text/plain, text/html, application/xml - depending on the content)
|
|
267
|
-
2. object/array (application/json)
|
|
268
|
-
3. boolean (text/plain)
|
|
269
|
-
4. readable stream (you must specify `Content-Type` and `Content-Length` headers yourself)
|
|
270
|
-
|
|
271
|
-
**Raw Response**: When it is needed to take the full control of the response, use composable function `useResponse`
|
|
272
|
-
|
|
273
|
-
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.
|
|
274
|
-
|
|
275
|
-
An example of using raw response instance:
|
|
276
|
-
```js
|
|
277
|
-
import { useResponse } from '@wooksjs/composables'
|
|
278
|
-
app.get('test', () => {
|
|
279
|
-
const { rawResponse } = useResponse()
|
|
280
|
-
const res = rawResponse()
|
|
281
|
-
res.writeHead(200, {})
|
|
282
|
-
res.end('ok')
|
|
283
|
-
})
|
|
284
|
-
```
|
|
285
|
-
|
|
286
|
-
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.
|
|
287
|
-
The next example does the same thing as the previous example using `passthrough` options:
|
|
288
|
-
|
|
289
|
-
```js
|
|
290
|
-
import { useResponse } from '@wooksjs/composables'
|
|
291
|
-
app.get('test', () => {
|
|
292
|
-
const { rawResponse } = useResponse()
|
|
293
|
-
const res = rawResponse({ passthrough: true })
|
|
294
|
-
return 'ok'
|
|
295
|
-
})
|
|
296
|
-
```
|
|
297
|
-
|
|
298
|
-
### Response Headers
|
|
299
|
-
|
|
300
|
-
A function `useSetHeaders` provides variety of response headers helpers:
|
|
301
|
-
|
|
302
|
-
```js
|
|
303
|
-
import { useSetHeaders, contentTypes } from '@wooksjs/composables'
|
|
304
|
-
app.get('test', async () => {
|
|
305
|
-
const {
|
|
306
|
-
setHeader, //sets header: (name: string, value: string | number) => void;
|
|
307
|
-
removeHeader, //removes header: (name: string) => void;
|
|
308
|
-
setContentType, //sets "Content-Type": (value: string) => void;
|
|
309
|
-
headers, //Object with response headers: Record<string, string>;
|
|
310
|
-
enableCors, //sets "Access-Control-Allow-Origin": (origin?: string) => void;
|
|
311
|
-
} = useSetHeaders()
|
|
312
|
-
|
|
313
|
-
setContentType(contentTypes.application.json)
|
|
314
|
-
setHeader('server', 'myServer v1.0')
|
|
315
|
-
enableCors()
|
|
316
|
-
return '{ "value": "OK" }'
|
|
317
|
-
})
|
|
318
|
-
```
|
|
319
|
-
|
|
320
|
-
Another hook for set header
|
|
321
|
-
|
|
322
|
-
```js
|
|
323
|
-
import { useRespHeader } from '@wooksjs/composables'
|
|
324
|
-
app.get('test', async () => {
|
|
325
|
-
const server = useRespHeader('server')
|
|
326
|
-
server.value = 'myServer v1.0'
|
|
327
|
-
})
|
|
328
|
-
```
|
|
329
|
-
|
|
330
|
-
### Response Cookies (Set-Cookie)
|
|
331
|
-
|
|
332
|
-
A function `useSetCookies` provides variety of set-cookie helpers:
|
|
333
|
-
|
|
334
|
-
```js
|
|
335
|
-
import { useSetCookies } from '@wooksjs/composables'
|
|
336
|
-
app.get('test', async () => {
|
|
337
|
-
const {
|
|
338
|
-
setCookie, // sets cookie : (name: string, value: string, attrs?) => void;
|
|
339
|
-
removeCookie, // removes cookie from setlist : (name: string) => void;
|
|
340
|
-
clearCookies, // removes all the cookies from setlist : () => void;
|
|
341
|
-
cookies, // returns a value of Set-Cookie header: () => string[];
|
|
342
|
-
} = useSetCookies()
|
|
343
|
-
|
|
344
|
-
setCookie('session', 'value', {
|
|
345
|
-
expires: '2029-01-01', // Date | string | number;
|
|
346
|
-
maxAge: '1h', // number | TProstoTimeMultiString;
|
|
347
|
-
domain: 'my-domain', // string;
|
|
348
|
-
path: '/home', // string;
|
|
349
|
-
secure: true, // boolean;
|
|
350
|
-
httpOnly: false, // boolean;
|
|
351
|
-
sameSite: true, // boolean | 'Lax' | 'None' | 'Strict';
|
|
352
|
-
})
|
|
353
|
-
})
|
|
354
|
-
```
|
|
355
|
-
|
|
356
|
-
Another hook for set-cookie
|
|
357
|
-
|
|
358
|
-
```js
|
|
359
|
-
import { useRespCookie } from '@wooksjs/composables'
|
|
360
|
-
app.get('test', async () => {
|
|
361
|
-
const session = useRespCookie('session')
|
|
362
|
-
session.value = 'value'
|
|
363
|
-
session.attrs = {
|
|
364
|
-
expires: '2029-01-01', // Date | string | number;
|
|
365
|
-
maxAge: '1h', // number | TProstoTimeMultiString;
|
|
366
|
-
domain: 'my-domain', // string;
|
|
367
|
-
path: '/home', // string;
|
|
368
|
-
secure: true, // boolean;
|
|
369
|
-
httpOnly: false, // boolean;
|
|
370
|
-
sameSite: true, // boolean | 'Lax' | 'None' | 'Strict';
|
|
371
|
-
}
|
|
372
|
-
})
|
|
373
|
-
```
|
|
374
|
-
|
|
375
|
-
### Response Status
|
|
376
|
-
|
|
377
|
-
It's possible to control the response status via `status` function that is available in `useResponse()`
|
|
378
|
-
|
|
379
|
-
```js
|
|
380
|
-
import { useResponse } from '@wooksjs/composables'
|
|
381
|
-
app.get('test', async () => {
|
|
382
|
-
const { status } = useResponse()
|
|
383
|
-
status(201) // sets status 201 for the response
|
|
384
|
-
console.log(status()) // when called with no argument returns the status
|
|
385
|
-
return 'response with status 201'
|
|
386
|
-
})
|
|
387
|
-
```
|
|
388
|
-
|
|
389
|
-
Another status hook:
|
|
390
|
-
```js
|
|
391
|
-
import { useStatus } from '@wooksjs/composables'
|
|
392
|
-
app.get('test', async () => {
|
|
393
|
-
const status = useStatus()
|
|
394
|
-
status.value = 201
|
|
395
|
-
return 'response with status 201'
|
|
396
|
-
})
|
|
397
|
-
```
|
|
398
|
-
|
|
399
|
-
### Cache-Control
|
|
400
|
-
|
|
401
|
-
`useSetCacheControl` function provides helpers for headers responsible for cache control
|
|
402
|
-
|
|
403
|
-
```js
|
|
404
|
-
import { useSetCacheControl } from '@wooksjs/composables'
|
|
405
|
-
app.get('static/*', () => {
|
|
406
|
-
const {
|
|
407
|
-
setAge, // sets Age (v: number | TProstoTimeMultiString) => void
|
|
408
|
-
setExpires, // sets Expires (v: Date | string | number) => void
|
|
409
|
-
setPragmaNoCache, // sets Pragma: no-cache (v: boolean) => void
|
|
410
|
-
setCacheControl, // sets Cache-Control (data: TCacheControl) => void
|
|
411
|
-
} = useSetCacheControl()
|
|
412
|
-
|
|
413
|
-
setAge('2h 15m')
|
|
414
|
-
setExpires('2022-05-05')
|
|
415
|
-
setCacheControl({
|
|
416
|
-
mustRevalidate: true,
|
|
417
|
-
noCache: false,
|
|
418
|
-
noStore: false,
|
|
419
|
-
noTransform: true,
|
|
420
|
-
public: true,
|
|
421
|
-
private: 'field',
|
|
422
|
-
proxyRevalidate: true,
|
|
423
|
-
maxAge: '3h 30m 12s',
|
|
424
|
-
sMaxage: '2h 27m 54s',
|
|
425
|
-
})
|
|
426
|
-
})
|
|
427
|
-
```
|
|
428
|
-
|
|
429
|
-
### Proxy Requests
|
|
430
|
-
|
|
431
|
-
`npm install @wooksjs/proxy`
|
|
432
|
-
|
|
433
|
-
Wooks provides support for proxy request/response
|
|
434
|
-
|
|
435
|
-
```js
|
|
436
|
-
import { useProxy } from '@wooksjs/proxy'
|
|
437
|
-
import { useRequest } from '@wooksjs/composables'
|
|
438
|
-
//...
|
|
439
|
-
app.get('*', async () => {
|
|
440
|
-
const proxy = useProxy()
|
|
441
|
-
const { url } = useRequest()
|
|
442
|
-
const fetchResponse = await proxy('https://www.google.com' + url, {
|
|
443
|
-
// optional method, be default is set with
|
|
444
|
-
// the original request method
|
|
445
|
-
method: 'GET',
|
|
446
|
-
|
|
447
|
-
// the next four options help to filter out
|
|
448
|
-
// request/response headers/cookies
|
|
449
|
-
// each of the option accepts an object with:
|
|
450
|
-
// - allow: '*' | (string | RegExp)[] - a list to allow (default '*')
|
|
451
|
-
// - block: '*' | (string | RegExp)[] - a list to block
|
|
452
|
-
// - overwrite: Record<string| strgin> | ((data: object) -> object) - object or fn to overwrite data
|
|
453
|
-
reqHeaders: { block: ['referer'] },
|
|
454
|
-
reqCookies: { allow: ['cookie-to-pass-downstream'] },
|
|
455
|
-
resHeaders: { overwrite: { 'x-proxied-by': 'wooks-proxy' } },
|
|
456
|
-
resCookies: { allow: ['cookie-to-pass-upstream'] },
|
|
457
|
-
|
|
458
|
-
// debug: true - will print proxy paths and headers/cookies
|
|
459
|
-
debug: true,
|
|
460
|
-
})
|
|
461
|
-
return fetchResponse // fetch response is supported, the body will be upstreamed
|
|
462
|
-
|
|
463
|
-
// > you can also return fully buffered body as Uint8Array
|
|
464
|
-
// return new Uint8Array(await fetchResponse.arrayBuffer())
|
|
465
|
-
|
|
466
|
-
// > or as string
|
|
467
|
-
// return fetchResponse.text()
|
|
468
|
-
|
|
469
|
-
// > or change response before return
|
|
470
|
-
// const data = await fetchResponse.text() + '<new data>'
|
|
471
|
-
// return data
|
|
472
|
-
})
|
|
473
|
-
//...
|
|
474
|
-
```
|
|
475
|
-
|
|
476
|
-
### Serve File (Serve-Static)
|
|
477
|
-
|
|
478
|
-
`npm install @wooksjs/serve-file`
|
|
479
|
-
|
|
480
|
-
Function `serveFile` returns a readable stream and prepares all the neccessary response headers (like content-length, content-type etc).
|
|
481
|
-
|
|
482
|
-
It can handle etag and range as well.
|
|
483
|
-
|
|
484
|
-
```js
|
|
485
|
-
import { serveFile } from '@wooksjs/serve-file'
|
|
486
|
-
// ...
|
|
487
|
-
serveFile(filePath, options)
|
|
488
|
-
```
|
|
489
|
-
|
|
490
|
-
**serveFile options**
|
|
491
|
-
```ts
|
|
492
|
-
{
|
|
493
|
-
// Any header to add
|
|
494
|
-
headers?: Record<string, string>
|
|
495
|
-
|
|
496
|
-
// Cache-Control header
|
|
497
|
-
cacheControl?: TCacheControl
|
|
498
|
-
|
|
499
|
-
// Expires header
|
|
500
|
-
expires?: Date | string | number
|
|
501
|
-
|
|
502
|
-
// when true a header "Pragma: no-cache" will be added
|
|
503
|
-
pragmaNoCache?: boolean
|
|
504
|
-
|
|
505
|
-
// the base directory path
|
|
506
|
-
baseDir?: string
|
|
507
|
-
|
|
508
|
-
// default extension will be added to the filePath
|
|
509
|
-
defaultExt?: string
|
|
510
|
-
|
|
511
|
-
// when true lists files in directory
|
|
512
|
-
listDirectory?: boolean
|
|
513
|
-
|
|
514
|
-
// put 'index.html'
|
|
515
|
-
// to automatically serve it from the folder
|
|
516
|
-
index?: string
|
|
517
|
-
}
|
|
518
|
-
```
|
|
519
|
-
|
|
520
|
-
Built-in file server example:
|
|
521
|
-
|
|
522
|
-
```js
|
|
523
|
-
import { useRouteParams } from '@wooksjs/composables'
|
|
524
|
-
import { serveFile } from '@wooksjs/serve-file'
|
|
525
|
-
app.get('static/*', () => {
|
|
526
|
-
const { getRouteParam } = useRouteParams()
|
|
527
|
-
return serveFile(getRouteParam('*'), { cacheControl: { maxAge: '10m' } })
|
|
528
|
-
})
|
|
529
|
-
```
|
|
530
|
-
|
|
531
|
-
`cacheControl` here is the same object as used in `useSetCacheControl().setCacheControl({ ... })`
|
|
532
|
-
|
|
533
|
-
## Error Handling
|
|
534
|
-
|
|
535
|
-
All the exeptions occured in handler are cought by the framework and interpreted as Server Error 500.
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
```js
|
|
539
|
-
app.get('error', () => {
|
|
540
|
-
throw new Error('Some Error')
|
|
541
|
-
// A call of this endpoint will result in
|
|
542
|
-
// 500 Internal Server Error
|
|
543
|
-
// "Some Error"
|
|
544
|
-
})
|
|
545
|
-
```
|
|
546
|
-
|
|
547
|
-
By default the Error Handler renders the response according to the `Accept` request header:
|
|
548
|
-
- if it accepts 'application/json' then the response will be in JSON format
|
|
549
|
-
- else if it accepts 'text/html' then the response will be in HTML format
|
|
550
|
-
- else if it accepts 'text/plain' then the response will be rendered in a plain text
|
|
551
|
-
- else the response will be in JSON format anyways
|
|
552
|
-
|
|
553
|
-
It's possible to return your own error:
|
|
554
|
-
|
|
555
|
-
```js
|
|
556
|
-
import { WooksError } from '@wooksjs/composables'
|
|
557
|
-
app.get('error', () => {
|
|
558
|
-
throw new WooksError('429', 'My Description')
|
|
559
|
-
// A call of this endpoint will result in
|
|
560
|
-
// 429 Too Many Requests
|
|
561
|
-
// "My Description"
|
|
562
|
-
})
|
|
563
|
-
```
|
|
564
|
-
|
|
565
|
-
In this case if you have an alternative (fallback) handler for the same route the error may not occure, the next handler will be called instead.
|
|
566
|
-
|
|
567
|
-
As an alternative you may not throw the error but return its instance:
|
|
568
|
-
|
|
569
|
-
```js
|
|
570
|
-
import { WooksError } from '@wooksjs/composables'
|
|
571
|
-
app.get('error', () => {
|
|
572
|
-
return new WooksError('429', 'My Description')
|
|
573
|
-
// A call of this endpoint will result in
|
|
574
|
-
// 429 Too Many Requests
|
|
575
|
-
// "My Description"
|
|
576
|
-
})
|
|
577
|
-
```
|
|
578
|
-
|
|
579
|
-
In this case if you have an alternative (fallback) handler for the same route the error will occure anyways as you explicitly return its instance.
|
|
580
|
-
|
|
581
|
-
## Alternative (Fallback) Handler
|
|
582
|
-
|
|
583
|
-
It's possible to assign several handlers for the same route. Every next handler will work as a fallback for the previous one.
|
|
584
|
-
|
|
585
|
-
The fallback handler is called only when exception is thrown out of the previous handler.
|
|
586
|
-
|
|
587
|
-
If the previous handler returns an Error Instance then the fallback handler won't be called.
|
|
588
|
-
|
|
589
|
-
For example you serve files, but for some 'not found' files you want to do something else:
|
|
590
|
-
|
|
591
|
-
```js
|
|
592
|
-
import { Wooks, useRouteParams } from '@wooksjs/composables'
|
|
593
|
-
import { serveFile } from '@wooksjs/serve-file'
|
|
594
|
-
const app = new Wooks()
|
|
595
|
-
|
|
596
|
-
app.get('static/*', () => {
|
|
597
|
-
const { getRouteParam } = useRouteParams()
|
|
598
|
-
// serveFile will throw 404 error if the file is not found
|
|
599
|
-
return serveFile(getRouteParam('*'), { maxAge: '10m' })
|
|
600
|
-
})
|
|
601
|
-
|
|
602
|
-
app.get('static/*', () => {
|
|
603
|
-
// this handler will be called every time the file is not found
|
|
604
|
-
return 'Here\'s my fallback response'
|
|
605
|
-
})
|
|
606
|
-
|
|
607
|
-
app.listen(3000)
|
|
608
|
-
```
|
|
609
|
-
|
|
610
|
-
In order to prevent the fallback to be invoked you must return an Error Instance explicitly:
|
|
611
|
-
|
|
612
|
-
```js
|
|
613
|
-
import { Wooks, useRouteParams } from '@wooksjs/composables'
|
|
614
|
-
import { serveFile } from '@wooksjs/serve-file'
|
|
615
|
-
const app = new Wooks()
|
|
616
|
-
|
|
617
|
-
app.get('static/*', () => {
|
|
618
|
-
const { getRouteParam } = useRouteParams()
|
|
619
|
-
try {
|
|
620
|
-
return serveFile(getRouteParam('*'), { maxAge: '10m' })
|
|
621
|
-
}
|
|
622
|
-
catch (e) {
|
|
623
|
-
// now we catch error and return it explicitly
|
|
624
|
-
return e
|
|
625
|
-
}
|
|
626
|
-
})
|
|
627
|
-
|
|
628
|
-
app.get('static/*', () => {
|
|
629
|
-
// this handler will be never called now
|
|
630
|
-
return 'Here\'s my fallback response which is never (ever) called'
|
|
631
|
-
})
|
|
632
|
-
|
|
633
|
-
app.listen(3000)
|
|
634
|
-
```
|
|
124
|
+
[More details on how to use composables here](https://github.com/wooksjs/composables)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wooks",
|
|
3
|
-
"version": "0.0.1-beta.
|
|
3
|
+
"version": "0.0.1-beta.8",
|
|
4
4
|
"description": "Web Application Framework with hooks",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"module": "dist/wooks.esm-bundler.js",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"@prostojs/router": "^0.0.14",
|
|
45
|
-
"@wooksjs/composables": "^0.0.1-alpha.
|
|
45
|
+
"@wooksjs/composables": "^0.0.1-alpha.8"
|
|
46
46
|
},
|
|
47
47
|
"gitHooks": {
|
|
48
48
|
"commit-msg": "node scripts/verifyCommit.js"
|
|
@@ -64,9 +64,9 @@
|
|
|
64
64
|
"@types/node-fetch": "^2.6.2",
|
|
65
65
|
"@typescript-eslint/eslint-plugin": "^5.42.0",
|
|
66
66
|
"@typescript-eslint/parser": "^5.0.0",
|
|
67
|
-
"@wooksjs/body": "^0.0.1-alpha.
|
|
67
|
+
"@wooksjs/body": "^0.0.1-alpha.4",
|
|
68
68
|
"@wooksjs/proxy": "^0.0.1-alpha.1",
|
|
69
|
-
"@wooksjs/serve-file": "^0.0.1-alpha.
|
|
69
|
+
"@wooksjs/serve-file": "^0.0.1-alpha.2",
|
|
70
70
|
"brotli": "^1.3.2",
|
|
71
71
|
"conventional-changelog": "^3.1.24",
|
|
72
72
|
"conventional-changelog-cli": "^2.1.1",
|