この記事何?
エンジニア歴1年半。業務で利用しているHonoが大好きだが、TSもプログラミング知識も弱々すぎて上手く使いこなせない。速いはずが多分生かせてない。
ちゃんと理解するためにソースコードリーディングしたい。
でも目的なくソースコード眺めても意味ないし……ねむい……
そうだ!PRを全部読めば、変遷やなぜ変更されているかストーリー的に分かるのでは。
と思ったのでチャレンジしてみる。PR2000以上あるので、全部できるかは知らん。
https://github.com/honojs/hono
#86 feat: Basic-auth with polyfill
Basic Auth のポリフィル対応を強化。Fastly Compute@Edge など、より多くの環境で動作するように改善。
sha256 関数をutilsに追加し、関数が環境を自動判定してくれる
src/utils/buffer.ts:
export const sha256 = async (a: string): Promise<string> => {
// crypto.subtle を試す(Cloudflare Workers, ブラウザ)
if (crypto && crypto.subtle) {
const buffer = await crypto.subtle.digest(
{ name: 'SHA-256' },
new TextEncoder().encode(String(a))
)
const hash = Array.prototype.map
.call(new Uint8Array(buffer), (x) => ('00' + x.toString(16)).slice(-2))
.join('')
return hash
}
// crypto.subtle がなければ Node.js の crypto を試す
try {
const crypto = await import('crypto')
const hash = crypto.createHash('sha256').update(a).digest('hex')
return hash
} catch (e) {
console.error('If you want to do "sha256", polyfill "crypto" module.')
throw e
}
}
| 環境 | decodeBase64 | sha256 |
|---|---|---|
| Cloudflare Workers | atob | crypto.subtle |
| ブラウザ | atob | crypto.subtle |
| Node.js | Buffer | crypto.createHash |
| Fastly Compute@Edge | atob (polyfill) | crypto.subtle (polyfill) |
#87 fix: use require
await import('crypto') を require('crypto') に変更。
#88 fix: default content-type
Content-Type ヘッダーを上書きしないように修正。ユーザーが明示的に設定した場合はそれを尊重。
// 変更前:
text(text: string, status: number = this._status, headers: Headers = {}): Response {
if (typeof text !== 'string') {
throw new TypeError('text method arg must be a string!')
}
headers['Content-Type'] = 'text/plain' // 常に上書き
return this.body(text, status, headers)
}
修正
src/context.ts:
text(text: string, status: number = this._status, headers: Headers = {}): Response {
if (typeof text !== 'string') {
throw new TypeError('text method arg must be a string!')
}
- headers['Content-Type'] = 'text/plain'
+ headers['Content-Type'] ||= 'text/plain; charset=UTF-8'
return this.body(text, status, headers)
}
json(object: object, status: number = this._status, headers: Headers = {}): Response {
if (typeof object !== 'object') {
throw new TypeError('json method arg must be an object!')
}
const body = JSON.stringify(object)
- headers['Content-Type'] = 'application/json; charset=UTF-8'
+ headers['Content-Type'] ||= 'application/json; charset=UTF-8'
return this.body(body, status, headers)
}
html(html: string, status: number = this._status, headers: Headers = {}): Response {
if (typeof html !== 'string') {
throw new TypeError('html method arg must be a string!')
}
- headers['Content-Type'] = 'text/html; charset=UTF-8'
+ headers['Content-Type'] ||= 'text/html; charset=UTF-8'
return this.body(html, status, headers)
}
#89 feat: add root option on mustache middleware
Mustache ミドルウェアに root オプションを追加。テンプレートファイルのルートディレクトリを指定できるように。
src/middleware/mustache/mustache.ts:
type Options = {
root: string
}
// 変更前
-export const mustache = () => {
// 変更後
+export const mustache = (opt: Options = { root: '' }) => {
+ const { root } = opt
return async (c: Context, next: Function) => {
// ...
c.render = async (filename, view = {}, options?) => {
// 変更前: 直接ファイル名を使う
- const buffer = await getContentFromKVAsset(`${filename}${EXTENSION}`)
// 変更後: getKVFilePath でパスを生成
+ const path = getKVFilePath({
+ filename: `${filename}${EXTENSION}`,
+ root: root,
+ defaultDocument: DEFAULT_DOCUMENT
+ })
+ const buffer = await getContentFromKVAsset(path)
if (!buffer) {
- throw new Error(`Template "${filename}${EXTENSION}" is not found or blank.`)
+ throw new Error(`Template "${path}" is not found or blank.`)
}
// ...
}
}
}
#90: test: add default middleware test
デフォルトミドルウェアのテストを追加。
余裕がなくなってきた〜。終わり。