小记 | 使用 Hono 简化 Electron 自定义协议处理
Table of Contents
前情提要 #
Electron
、Hono
以及 Service Worker
等技术有一定了解引入 #
开发 Electron
应用的都知道,在其模块 protocol
中提供了一个方法protocol.registerSchemesAsPrivileged(customSchemes)
用于自定义协议
而后,可以通过 protocol.handle(scheme, handler)
1对请求进行处理
本文所说的,即发生在 handler
中
正文 #
一般写法如下
app.whenReady().then(() => {
protocol.handle("app", (req) => {
const { host, pathname } = new URL(req.url);
if (host === "bundle") {
if (pathname === "/") {
return new Response("hello, world!"});
}
}
});
});
熟悉 Service Worker 的都知道,在 SW 中也有一个 FetchEvent,用于拦截请求并自定义响应,其写法大致(省略部分代码)如下
self.addEventListener("fetch", (event) => {
event.respondWith(new Response("hello, world!"));
});
这样可能不能说明什么,但如果我们将响应提到 handler
中呢?
const fetchHandler = () => {
return new Response("hello, world!");
};
self.addEventListener("fetch", (event) => {
event.respondWith(fetchHandler());
});
这时候,我们发现 handler
部分就和 protocol.handle
的 handler
一致了
既然它们很相像,那么 Service Worker
上的 handler
是不是也能给 Electron
用?
这时候,我突然想起 Hono
这个框架,它不也是 handler
么?
而且 Hono
用起来更加简洁,还支持链式路由,比写一大堆 if-else
好多了
于是,我就尝试用 Hono
来作为 protocol.handle
的 handler
尝试适配 #
理所当然,我们应该查看 Hono
文档中关于 Service Worker 适配器 的部分,文档中 self.addEventListener('fetch', handle(app))
的 handle(app)
就是 handler
了
定位到 handle
函数的来源:src/adapter/service-worker/handler.ts
其实最后就是传入了一个类型为 Hono
的对象 app
,调用 app.fetch()
而 Hono 文档:App - Hono - Hono 的解释:「 app.fetch
will be entry point of your application. 」也说明 app.fetch
就是我们需要的东西
所以,直接传入 Request
2就好了
……吗?
我们简单变换代码,并把 Hono
的逻辑移到 protocolHandler.js
中
// main.js
import { app, protocol } from "electron";
import { protocolApp } from "./utils/protocolHandler.js";
app.whenReady().then(() => {
protocol.handle("app", async (req) => {
await protocolApp.fetch(req);
});
});
// protocolHandler.js
import { Hono } from "hono";
const app = new Hono();
app.get("/bundle/", (c) => {
return c.text("hello, world!");
});
export const protocolApp = app;
请求 app://bundle/
,会发现得到 404,是 Hono
没生效吗?但是我们如果定义 notFound
app.notFound((c) => {
return c.text(`You're trying to get response from: ${c.req.path}, But it's undefined.`, 404);
});
会发现 Hono
已经成功处理了请求,但是为什么还是 404?
我们看看响应:You're trying to get response from: //bundle/, But it's undefined.
咦,路由怎么变成这样了,关键点在 //bundle/
,我们想要访问 app://bundle/
能被 Hono
响应,那我们将路由修改为 //bundle/
呢?
发现 Hono
能够响应了,但是每次这样写路由也太阴间了,所以我们需要简化一下
通过输出日志判断,Hono
将 macaron:
删除,把 //bundle/
当作 path
,因此,只需要指定 Hono
的工作路径(basePath
)就可以解决
但 basePath
不能为 /
,因为 Hono
默认路径就是 /
,不知道为什么需要写阴间路由
不过我们可以指定 basePath
为 //
const app = new Hono().basePath("//");
然后修改路由
app.get('bundle/', async (c) => {
return c.text('hello, world!');
});
请求,发现完美解决问题
又是麻烦的一天呢😡