hono 0.5.1 → 0.5.4
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 +70 -38
- package/dist/context.js +2 -2
- package/dist/hono.d.ts +14 -5
- package/dist/hono.js +4 -0
- package/dist/middleware/basic-auth/basic-auth.d.ts +1 -0
- package/dist/middleware/basic-auth/basic-auth.js +2 -2
- package/dist/utils/buffer.d.ts +1 -1
- package/dist/utils/buffer.js +6 -3
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
# Hono
|
|
1
|
+
# Hono\[炎\]
|
|
2
|
+
|
|
3
|
+
<p>
|
|
4
|
+
<a href="https://github.com/yusukebe/hono/blob/master/README.md">English</a>
|
|
5
|
+
·
|
|
6
|
+
<a href="https://github.com/yusukebe/hono/blob/master/docs/README.ja.md">日本語</a>
|
|
7
|
+
</p>
|
|
2
8
|
|
|
3
9
|
[](https://github.com/yusukebe/hono/actions)
|
|
4
10
|
[](https://github.com/yusukebe/hono/blob/master/LICENSE)
|
|
@@ -8,7 +14,7 @@
|
|
|
8
14
|
[](https://github.com/yusukebe/hono/pulse)
|
|
9
15
|
[](https://github.com/yusukebe/hono/commits/master)
|
|
10
16
|
|
|
11
|
-
Hono[炎] - _**means flame🔥 in Japanese**_ - is small, simple, and ultrafast web framework for
|
|
17
|
+
Hono[炎] - _**means flame🔥 in Japanese**_ - is small, simple, and ultrafast web framework for Cloudflare Workers and Fastly Compute@Edge.
|
|
12
18
|
|
|
13
19
|
```js
|
|
14
20
|
import { Hono } from 'hono'
|
|
@@ -22,13 +28,13 @@ app.fire()
|
|
|
22
28
|
## Features
|
|
23
29
|
|
|
24
30
|
- **Ultrafast** - the router does not use linear loops.
|
|
25
|
-
- **Zero-dependencies** - using only Web standard API.
|
|
26
|
-
- **Middleware** -
|
|
31
|
+
- **Zero-dependencies** - using only Service Worker and Web standard API.
|
|
32
|
+
- **Middleware** - built-in middleware and ability to extend with your own middleware.
|
|
27
33
|
- **Optimized** - for Cloudflare Workers.
|
|
28
34
|
|
|
29
35
|
## Benchmark
|
|
30
36
|
|
|
31
|
-
**Hono is fastest
|
|
37
|
+
**Hono is fastest**, compared to other routers for Cloudflare Workers.
|
|
32
38
|
|
|
33
39
|
```plain
|
|
34
40
|
hono x 809,503 ops/sec ±6.94% (73 runs sampled)
|
|
@@ -41,7 +47,7 @@ Fastest is hono
|
|
|
41
47
|
|
|
42
48
|
## Hono in 1 minute
|
|
43
49
|
|
|
44
|
-
A demonstration to create an application
|
|
50
|
+
A demonstration to create an application for Cloudflare Workers with Hono.
|
|
45
51
|
|
|
46
52
|

|
|
47
53
|
|
|
@@ -53,13 +59,13 @@ Now, the named path parameter has types.
|
|
|
53
59
|
|
|
54
60
|
You can install Hono from the npm registry.
|
|
55
61
|
|
|
56
|
-
```
|
|
62
|
+
```
|
|
57
63
|
$ yarn add hono
|
|
58
64
|
```
|
|
59
65
|
|
|
60
66
|
or
|
|
61
67
|
|
|
62
|
-
```
|
|
68
|
+
```
|
|
63
69
|
$ npm install hono
|
|
64
70
|
```
|
|
65
71
|
|
|
@@ -75,6 +81,7 @@ An instance of `Hono` has these methods.
|
|
|
75
81
|
- app.**onError**(err, handler)
|
|
76
82
|
- app.**fire**()
|
|
77
83
|
- app.**fetch**(request, env, event)
|
|
84
|
+
- app.**request**(path, option)
|
|
78
85
|
|
|
79
86
|
## Routing
|
|
80
87
|
|
|
@@ -147,7 +154,9 @@ app.get('/fetch-url', async (c) => {
|
|
|
147
154
|
|
|
148
155
|
## Middleware
|
|
149
156
|
|
|
150
|
-
###
|
|
157
|
+
### Built-in Middleware
|
|
158
|
+
|
|
159
|
+
Hono has built-in middleware.
|
|
151
160
|
|
|
152
161
|
```js
|
|
153
162
|
import { Hono } from 'hono'
|
|
@@ -168,7 +177,7 @@ app.use(
|
|
|
168
177
|
)
|
|
169
178
|
```
|
|
170
179
|
|
|
171
|
-
Available
|
|
180
|
+
Available built-in middleware is listed on [src/middleware](https://github.com/yusukebe/hono/tree/master/src/middleware).
|
|
172
181
|
|
|
173
182
|
### Custom Middleware
|
|
174
183
|
|
|
@@ -213,7 +222,7 @@ app.onError((err, c) => {
|
|
|
213
222
|
|
|
214
223
|
## Context
|
|
215
224
|
|
|
216
|
-
To handle Request and Reponse, you can use Context object.
|
|
225
|
+
To handle Request and Reponse, you can use `Context` object.
|
|
217
226
|
|
|
218
227
|
### c.req
|
|
219
228
|
|
|
@@ -273,7 +282,7 @@ new Response('Thank you for comming', {
|
|
|
273
282
|
|
|
274
283
|
### c.text()
|
|
275
284
|
|
|
276
|
-
Render
|
|
285
|
+
Render text as `Content-Type:text/plain`.
|
|
277
286
|
|
|
278
287
|
```js
|
|
279
288
|
app.get('/say', (c) => {
|
|
@@ -303,7 +312,7 @@ app.get('/', (c) => {
|
|
|
303
312
|
|
|
304
313
|
### c.notFound()
|
|
305
314
|
|
|
306
|
-
Return the `
|
|
315
|
+
Return the `Not Found` Response.
|
|
307
316
|
|
|
308
317
|
```js
|
|
309
318
|
app.get('/notfound', (c) => {
|
|
@@ -379,51 +388,74 @@ export default app
|
|
|
379
388
|
*/
|
|
380
389
|
```
|
|
381
390
|
|
|
391
|
+
## request
|
|
392
|
+
|
|
393
|
+
`request` is a useful method for testing.
|
|
394
|
+
|
|
395
|
+
```js
|
|
396
|
+
test('GET /hello is ok', async () => {
|
|
397
|
+
const res = await app.request('http://localhost/hello')
|
|
398
|
+
expect(res.status).toBe(200)
|
|
399
|
+
})
|
|
400
|
+
```
|
|
401
|
+
|
|
382
402
|
## Cloudflare Workers with Hono
|
|
383
403
|
|
|
384
|
-
Using
|
|
404
|
+
Using [Wrangler](https://developers.cloudflare.com/workers/cli-wrangler/) or [Miniflare](https://miniflare.dev), you can develop the application locally and publish it with few commands.
|
|
385
405
|
|
|
386
406
|
Let's write your first code for Cloudflare Workers with Hono.
|
|
387
407
|
|
|
388
|
-
|
|
408
|
+
---
|
|
389
409
|
|
|
390
|
-
|
|
410
|
+
### Caution
|
|
391
411
|
|
|
392
|
-
|
|
393
|
-
$ npm i @cloudflare/wrangler -g
|
|
394
|
-
```
|
|
412
|
+
**Wrangler 1.x** does not support importing middleware. We recommend two ways:
|
|
395
413
|
|
|
396
|
-
|
|
414
|
+
1. Use [Wragler 2.0 Beta](https://github.com/cloudflare/wrangler2).
|
|
415
|
+
2. Build without webpack 4.x. For example, you can use esbuild. See [the starter template](https://github.com/yusukebe/hono-minimal).
|
|
416
|
+
|
|
417
|
+
---
|
|
418
|
+
|
|
419
|
+
### 1. `npm init`
|
|
397
420
|
|
|
398
421
|
Make a npm skeleton directory.
|
|
399
422
|
|
|
400
|
-
```
|
|
401
|
-
mkdir hono-example
|
|
402
|
-
cd hono-example
|
|
403
|
-
npm init -y
|
|
423
|
+
```
|
|
424
|
+
$ mkdir hono-example
|
|
425
|
+
$ cd hono-example
|
|
426
|
+
$ npm init -y
|
|
404
427
|
```
|
|
405
428
|
|
|
406
|
-
###
|
|
429
|
+
### 2. `wrangler init`
|
|
407
430
|
|
|
408
|
-
|
|
431
|
+
Initialize as a wrangler project.
|
|
409
432
|
|
|
410
|
-
```
|
|
411
|
-
$ wrangler init
|
|
433
|
+
```
|
|
434
|
+
$ npx wrangler@beta init
|
|
412
435
|
```
|
|
413
436
|
|
|
414
|
-
|
|
437
|
+
Answer the questions. If you want, you can answer `y`.
|
|
438
|
+
|
|
439
|
+
```
|
|
440
|
+
Would you like to install wrangler into your package.json? (y/n) <--- n
|
|
441
|
+
Would you like to use TypeScript? (y/n) <--- n
|
|
442
|
+
Would you like to create a Worker at src/index.js? (y/n) <--- n
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
### 3. `npm install hono`
|
|
415
446
|
|
|
416
447
|
Install `hono` from the npm registry.
|
|
417
448
|
|
|
418
|
-
```
|
|
449
|
+
```
|
|
419
450
|
$ npm i hono
|
|
420
451
|
```
|
|
421
452
|
|
|
422
|
-
###
|
|
453
|
+
### 4. Write your app
|
|
423
454
|
|
|
424
455
|
Only 4 lines!!
|
|
425
456
|
|
|
426
457
|
```js
|
|
458
|
+
// index.js
|
|
427
459
|
import { Hono } from 'hono'
|
|
428
460
|
const app = new Hono()
|
|
429
461
|
|
|
@@ -432,25 +464,25 @@ app.get('/', (c) => c.text('Hello! Hono!'))
|
|
|
432
464
|
app.fire()
|
|
433
465
|
```
|
|
434
466
|
|
|
435
|
-
###
|
|
467
|
+
### 5. Run
|
|
436
468
|
|
|
437
469
|
Run the development server locally. Then, access `http://127.0.0.1:8787/` in your Web browser.
|
|
438
470
|
|
|
439
|
-
```
|
|
440
|
-
$ wrangler dev
|
|
471
|
+
```
|
|
472
|
+
$ npx wrangler@beta dev index.js
|
|
441
473
|
```
|
|
442
474
|
|
|
443
|
-
###
|
|
475
|
+
### 6. Publish
|
|
444
476
|
|
|
445
477
|
Deploy to Cloudflare. That's all!
|
|
446
478
|
|
|
447
|
-
```
|
|
448
|
-
$ wrangler publish
|
|
479
|
+
```
|
|
480
|
+
$ npx wrangler@beta publish index.js
|
|
449
481
|
```
|
|
450
482
|
|
|
451
483
|
## Starter template
|
|
452
484
|
|
|
453
|
-
You can start making your
|
|
485
|
+
You can start making your Cloudflare Workers application with [the starter template](https://github.com/yusukebe/hono-minimal). It is really minimal using TypeScript, esbuild, and Miniflare.
|
|
454
486
|
|
|
455
487
|
To generate a project skelton, run this command.
|
|
456
488
|
|
package/dist/context.js
CHANGED
|
@@ -35,8 +35,8 @@ class Context {
|
|
|
35
35
|
this._statusText = (0, http_status_1.getStatusText)(number);
|
|
36
36
|
}
|
|
37
37
|
newResponse(data, init = {}) {
|
|
38
|
-
init.status = init.status || this._status;
|
|
39
|
-
init.statusText = init.statusText || this._statusText;
|
|
38
|
+
init.status = init.status || this._status || 200;
|
|
39
|
+
init.statusText = init.statusText || this._statusText || (0, http_status_1.getStatusText)(init.status);
|
|
40
40
|
init.headers = Object.assign(Object.assign({}, this._headers), init.headers);
|
|
41
41
|
// Content-Length
|
|
42
42
|
let length = 0;
|
package/dist/hono.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/// <reference types="@cloudflare/workers-types" />
|
|
2
2
|
import { Context } from './context';
|
|
3
3
|
import type { Env } from './context';
|
|
4
|
-
import type {
|
|
4
|
+
import type { Router } from './router';
|
|
5
5
|
declare global {
|
|
6
6
|
interface Request<ParamKeyType = string> {
|
|
7
7
|
param: (key: ParamKeyType) => string;
|
|
@@ -26,25 +26,34 @@ export declare class Hono {
|
|
|
26
26
|
middlewareRouters: Router<MiddlewareHandler>[];
|
|
27
27
|
tempPath: string;
|
|
28
28
|
constructor(init?: Partial<Pick<Hono, 'routerClass' | 'strict'>>);
|
|
29
|
-
notFoundHandler
|
|
30
|
-
errorHandler
|
|
29
|
+
private notFoundHandler;
|
|
30
|
+
private errorHandler;
|
|
31
31
|
get<Path extends string>(path: Path, handler: Handler<ParamKeys<Path>>): Hono;
|
|
32
|
+
get(path: string, handler: Handler<string>): Hono;
|
|
32
33
|
post<Path extends string>(path: Path, handler: Handler<ParamKeys<Path>>): Hono;
|
|
34
|
+
post(path: string, handler: Handler<string>): Hono;
|
|
33
35
|
put<Path extends string>(path: Path, handler: Handler<ParamKeys<Path>>): Hono;
|
|
36
|
+
put(path: string, handler: Handler<string>): Hono;
|
|
34
37
|
head<Path extends string>(path: Path, handler: Handler<ParamKeys<Path>>): Hono;
|
|
38
|
+
head(path: string, handler: Handler<string>): Hono;
|
|
35
39
|
delete<Path extends string>(path: Path, handler: Handler<ParamKeys<Path>>): Hono;
|
|
40
|
+
delete(path: string, handler: Handler<string>): Hono;
|
|
36
41
|
options<Path extends string>(path: Path, handler: Handler<ParamKeys<Path>>): Hono;
|
|
42
|
+
options(path: string, handler: Handler<string>): Hono;
|
|
37
43
|
patch<Path extends string>(path: Path, handler: Handler<ParamKeys<Path>>): Hono;
|
|
44
|
+
patch(path: string, handler: Handler<string>): Hono;
|
|
38
45
|
all<Path extends string>(path: Path, handler: Handler<ParamKeys<Path>>): Hono;
|
|
46
|
+
all(path: string, handler: Handler<string>): Hono;
|
|
39
47
|
route(path: string): Hono;
|
|
40
48
|
use(path: string, middleware: MiddlewareHandler): void;
|
|
41
49
|
onError(handler: ErrorHandler): Hono;
|
|
42
50
|
notFound(handler: NotFoundHandler): Hono;
|
|
43
|
-
addRoute
|
|
44
|
-
matchRoute
|
|
51
|
+
private addRoute;
|
|
52
|
+
private matchRoute;
|
|
45
53
|
dispatch(request: Request, env?: Env, event?: FetchEvent): Promise<Response>;
|
|
46
54
|
handleEvent(event: FetchEvent): Promise<Response>;
|
|
47
55
|
fetch(request: Request, env?: Env, event?: FetchEvent): Promise<Response>;
|
|
56
|
+
request(input: RequestInfo, requestInit?: RequestInit): Promise<Response>;
|
|
48
57
|
fire(): void;
|
|
49
58
|
}
|
|
50
59
|
export {};
|
package/dist/hono.js
CHANGED
|
@@ -128,6 +128,10 @@ class Hono {
|
|
|
128
128
|
async fetch(request, env, event) {
|
|
129
129
|
return this.dispatch(request, env, event);
|
|
130
130
|
}
|
|
131
|
+
request(input, requestInit) {
|
|
132
|
+
const req = new Request(input, requestInit);
|
|
133
|
+
return this.dispatch(req);
|
|
134
|
+
}
|
|
131
135
|
fire() {
|
|
132
136
|
addEventListener('fetch', (event) => {
|
|
133
137
|
event.respondWith(this.handleEvent(event));
|
|
@@ -37,8 +37,8 @@ const basicAuth = (options, ...users) => {
|
|
|
37
37
|
const requestUser = auth(ctx.req);
|
|
38
38
|
if (requestUser) {
|
|
39
39
|
for (const user of users) {
|
|
40
|
-
const usernameEqual = await (0, buffer_1.timingSafeEqual)(user.username, requestUser.username);
|
|
41
|
-
const passwordEqual = await (0, buffer_1.timingSafeEqual)(user.password, requestUser.password);
|
|
40
|
+
const usernameEqual = await (0, buffer_1.timingSafeEqual)(user.username, requestUser.username, options.hashFunction);
|
|
41
|
+
const passwordEqual = await (0, buffer_1.timingSafeEqual)(user.password, requestUser.password, options.hashFunction);
|
|
42
42
|
if (usernameEqual && passwordEqual) {
|
|
43
43
|
// Authorized OK
|
|
44
44
|
return next();
|
package/dist/utils/buffer.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export declare const equal: (a: ArrayBuffer, b: ArrayBuffer) => boolean;
|
|
2
|
-
export declare const timingSafeEqual: (a: string | object | boolean, b: string | object | boolean) => Promise<boolean>;
|
|
2
|
+
export declare const timingSafeEqual: (a: string | object | boolean, b: string | object | boolean, hashFunction?: Function) => Promise<boolean>;
|
package/dist/utils/buffer.js
CHANGED
|
@@ -20,9 +20,12 @@ const equal = (a, b) => {
|
|
|
20
20
|
return true;
|
|
21
21
|
};
|
|
22
22
|
exports.equal = equal;
|
|
23
|
-
const timingSafeEqual = async (a, b) => {
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
const timingSafeEqual = async (a, b, hashFunction) => {
|
|
24
|
+
if (!hashFunction) {
|
|
25
|
+
hashFunction = crypto_1.sha256;
|
|
26
|
+
}
|
|
27
|
+
const sa = await hashFunction(a);
|
|
28
|
+
const sb = await hashFunction(b);
|
|
26
29
|
return sa === sb && a === b;
|
|
27
30
|
};
|
|
28
31
|
exports.timingSafeEqual = timingSafeEqual;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hono",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.4",
|
|
4
4
|
"description": "[炎] Ultrafast web framework for Cloudflare Workers.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -78,11 +78,13 @@
|
|
|
78
78
|
],
|
|
79
79
|
"devDependencies": {
|
|
80
80
|
"@cloudflare/workers-types": "^3.3.0",
|
|
81
|
+
"@types/crypto-js": "^4.1.1",
|
|
81
82
|
"@types/jest": "^27.4.0",
|
|
82
83
|
"@types/mustache": "^4.1.2",
|
|
83
84
|
"@types/node": "^17.0.8",
|
|
84
85
|
"@typescript-eslint/eslint-plugin": "^5.9.0",
|
|
85
86
|
"@typescript-eslint/parser": "^5.9.0",
|
|
87
|
+
"crypto-js": "^4.1.1",
|
|
86
88
|
"eslint": "^7.26.0",
|
|
87
89
|
"eslint-config-prettier": "^8.3.0",
|
|
88
90
|
"eslint-define-config": "^1.2.1",
|
|
@@ -96,6 +98,7 @@
|
|
|
96
98
|
"jest-environment-miniflare": "^2.0.0",
|
|
97
99
|
"mustache": "^4.2.0",
|
|
98
100
|
"prettier": "^2.5.1",
|
|
101
|
+
"prettier-plugin-md-nocjsp": "^1.2.0",
|
|
99
102
|
"rimraf": "^3.0.2",
|
|
100
103
|
"ts-jest": "^27.1.2",
|
|
101
104
|
"typescript": "^4.5.5"
|