この記事何?
エンジニア歴1年半。業務で利用しているHonoが大好きだが、TSもプログラミング知識も弱々すぎて上手く使いこなせない。速いはずが多分生かせてない。
ちゃんと理解するためにソースコードリーディングしたい。
でも目的なくソースコード眺めても意味ないし……ねむい……
そうだ!PRを全部読めば、変遷やなぜ変更されているかストーリー的に分かるのでは。
と思ったのでチャレンジしてみる。PR2000以上あるので、全部できるかは知らん。
https://github.com/honojs/hono
91 refactor: remove default middleware
デフォルトミドルウェアを削除。req.query(), req.header(), req.param() を Hono 本体に直接実装。
変更前:
// src/middleware/default.ts
export const defaultMiddleware = async (c: Context, next: Function) => {
c.req.query = (key: string) => {
const url = new URL(c.req.url)
return url.searchParams.get(key)
}
c.req.header = (name: string): string => {
return c.req.headers.get(name)
}
await next()
}
// src/hono.ts
middleware.push(Middleware.default) // デフォルトミドルウェアを追加
middleware.push(wrappedHandler)
修正
src/hono.ts:
const result = await this.matchRoute(method, path)
// Methods for Request object(直接 Request を拡張)
request.param = (key: string): string => {
if (result) {
return result.params[key]
}
}
request.header = (name: string): string => {
return request.headers.get(name)
}
request.query = (key: string): string => {
const url = new URL(c.req.url)
return url.searchParams.get(key)
}
// ミドルウェアチェーンの構築
-middleware.push(Middleware.default) // ← 削除
middleware.push(wrappedHandler)
src/middleware/default.ts:
ファイル自体を削除
92 Close
93 feat: auto set statusText
HTTP ステータスコードに対応する statusText を自動設定。c.status(404) を呼ぶだけで "Not Found" が設定される。
変更内容
- http-status.ts の追加
src/utils/http-status.ts:
export const getStatusText = (statusNumber: number): string => {
const text = statuses[statusNumber]
return text
}
const statuses: { [key: number]: string } = {
200: 'OK',
201: 'Created',
202: 'Accepted',
204: 'No Content',
206: 'Partial Content',
301: 'Moved Permanently',
302: 'Moved Temporarily',
303: 'See Other',
304: 'Not Modified',
307: 'Temporary Redirect',
308: 'Permanent Redirect',
400: 'Bad Request',
401: 'Unauthorized',
402: 'Payment Required',
403: 'Forbidden',
404: 'Not Found',
405: 'Not Allowed',
406: 'Not Acceptable',
408: 'Request Time-out',
409: 'Conflict',
410: 'Gone',
411: 'Length Required',
412: 'Precondition Failed',
413: 'Request Entity Too Large',
414: 'Request-URI Too Large',
415: 'Unsupported Media Type',
416: 'Requested Range Not Satisfiable',
421: 'Misdirected Request',
429: 'Too Many Requests',
500: 'Internal Server Error',
501: 'Not Implemented',
502: 'Bad Gateway',
503: 'Service Temporarily Unavailable',
504: 'Gateway Time-out',
505: 'HTTP Version Not Supported',
507: 'Insufficient Storage',
}
- c.status() の改善
src/context.ts:
import { getStatusText } from './utils/http-status'
status(number: number): void {
+ // 既に c.res が設定されている場合は警告
+ if (this.res) {
+ console.warn('c.res.status is already setted.')
+ return
+ }
this._status = number
+ this._statusText = getStatusText(number) // ← 自動で設定
}
-// statusText メソッドを削除(自動設定されるため不要)
-statusText(text: string): void {
- this._statusText = text
-}
- Data 型の定義
src/context.ts:
+type Data = string | ArrayBuffer | ReadableStream
export class Context {
// ...
- newResponse(data: any, init: ResponseInit = {}): Response {
+ newResponse(data: Data, init: ResponseInit = {}): Response {
// ...
}
- body(data: any, status: number = this._status, headers: Headers = this._headers): Response {
+ body(data: Data, status: number = this._status, headers: Headers = this._headers): Response {
// ...
}
}
使い方
変更前:
app.get('/not-found', (c) => {
c.status(404)
c.statusText('Not Found') // ← 手動で設定
return c.text('Page not found')
})
変更後:
app.get('/not-found', (c) => {
c.status(404) // statusText は自動で 'Not Found' に設定される
return c.text('Page not found')
})
レスポンス:
HTTP/1.1 404 Not Found
Content-Type: text/plain; charset=UTF-8
Page not found
知ってるようで使ってない機能たくさんあるわ....自前で返してた....
#94 feat: check response type
ハンドラーの戻り値が Response オブジェクトかチェック。型安全性を向上。
変更内容
- Response 型チェックの追加
src/hono.ts:
const wrappedHandler = async (context: Context, next: Function) => {
- context.res = await handler(context)
+ const res = await handler(context)
+ if (!(res instanceof Response)) {
+ throw new TypeError('response must be a instace of Response')
+ }
+ context.res = res
await next()
}
など、細々した型定義の修正などで正直よくわからん....
#95 Flamework to Framework
README のタイポ修正