文章摘要
加载中...|
此内容根据文章生成,并经过人工审核,仅用于文章内容的解释与总结 投诉

缘由

最近看到 DIYgod 大佬写的一篇文章:一个六岁开源项目的崩溃与新生,文中提到了他用 Homo Hono 框架替换了 RSSHub 项目原本使用的 Koa 框架。巧了,我正好也有几个项目在使用 Koa 框架,但是这也是第一次听说这个新框架,于是就打算学习一下看看,能不能用 Hono 框架来替换掉这个已经不太活跃的老框架。

安装

安装是必不可少的,在这里使用 pnpm 来安装:

bash
pnpm create hono my-app

在选择完基本信息后,进入安装目录安装依赖并运行:

bash
cd my-app
pnpm install
pnpm dev

程序将会默认运行在 3000 端口,若出现占用情况,可自行更换端口。( 3000 端口可太容易被占用了 )

请求和响应

Hono 基本上支持所有的请求类型,并且可返回多种类型的响应。

基本类型

常用的请求类型比如 GETPOSTPUTDELETE 请求:

js
import { serve } from "@hono/node-server";
import { Hono } from "hono";

const app = new Hono();

// GET
app.get("/", (c) => c.text("Hello Hono!"));

// POST
app.post("/", (c) => c.text("Hello Hono!"));

// PUT
app.put("/", (c) => c.text("Hello Hono!"));

// DELETE
app.delete("/", (c) => c.text("Hello Hono!"));

同时,Hono 也支持链式路线,这样能使代码更加清晰:

js
app
  .get("/test", (c) => {
    return c.text("GET /test");
  })
  .post((c) => {
    return c.text("POST /test");
  })
  .put((c) => {
    return c.text("PUT /test");
  });
  .delete((c) => {
    return c.text("DELETE /test");
  });

携带参数

在使用请求时,通常会携带参数,比如你想发送一个附带路径参数的 GET 请求:

http
GET 127.0.0.1:3000/posts/114514?username=homo

那么你可以使用 req.param() 方法来获取路径参数,req.query() 方法来获取携带参数:

js
app.get("/posts/:id", (c) => {
  // 获取路径参数
  const id = c.req.param("id");
  // 获取携带参数
  const username = c.req.query("username");
  return c.text(`获取由 ${username} 用户发表的 ID 为 ${id} 的文章`);
  // 获取由 homo 用户发表的 ID 为 114514 的文章
});

返回 HTML

Hono 也支持返回 HTML 类型的响应,你需要先定义一个 JSX 组件,例如:

jsx
const View = () => {
  return (
    <html>
      <body>
        <h1>Hello Hono!</h1>
      </body>
    </html>
  );
};

export default View;

然后便可在接口处返回:

js
app.get("/home", (c) => {
  return c.html(Home());
});

中间件

CORS

CORS 算是后端服务不可缺少的设置了,负责允许设置跨域资源共享( CORS )的响应头,以允许跨域请求。

js
import { Hono } from "hono";
import { cors } from "hono/cors";

const app = new Hono();

// 应用到所有路由
app.use("*", cors());

// 单独对某个接口设置
app.use(
  "/api2/*",
  cors({
    origin: "http://example.com",
    allowHeaders: ["X-Custom-Header", "Upgrade-Insecure-Requests"],
    allowMethods: ["POST", "GET", "OPTIONS"],
    exposeHeaders: ["Content-Length", "X-Kuma-Revision"],
    maxAge: 600,
    credentials: true,
  }),
);

CORS 参数

参数类型默认值描述
originstring | string[] | (origin: string) => string*Access-Control-Allow-Origin 的值。可以是一个确定的字符串,一个字符串数组,或是一个回调函数,如 origin: (origin) => (origin.endsWith('.example.com') ? origin : 'http://example.com')
allowMethodsstring[]['GET', 'HEAD', 'PUT', 'POST', 'DELETE', 'PATCH']Access-Control-Allow-Methods 的值,标明允许哪些 HTTP 请求方法。
allowHeadersstring[][]Access-Control-Allow-Headers 的值,标明在请求中允许设置哪些 HTTP 头部
maxAgenumber-Access-Control-Max-Age 的值,指定预检请求的结果能够被缓存多长时间。
credentialsboolean-Access-Control-Allow-Credentials 的值,标明是否允许请求的凭证模式(如Cookies)
exposeHeadersstring[][]Access-Control-Expose-Headers 的值,列出哪些头部可以被客户端 JavaScript 代码访问

CSRF

CSRF 是一种攻击手段,攻击者通过欺骗用户的浏览器,让其代为发起恶意请求,通常是在用户不知情的情况下,使用用户的登录身份执行一些操作。CSRF 攻击发生在第三方网站上,但是请求是发给受信任站点的,所以请求会带上用户的认证信息,如 Cookie。为了防止 CSRF 攻击,开发人员需要确保安全地验证用户请求的来源。

js
import { Hono } from "hono";
import { csrf } from "hono/csrf";

const app = new Hono();

// 使用 origin 选项指定允许的来源
app.use(csrf({ origin: "myapp.example.com" }));

// 使用 origin 选项指定多个允许的来源
app.use(
  csrf({
    origin: ["www.example.com", "development.example.com"],
  }),
);

同时还可以用函数的方式来进行匹配:

DANGER

强烈建议验证协议以确保与 $ 匹配,请永远不要使用 * 进行匹配

js
app.use(
  "*",
  csrf({
    // 使用正则表达式检查来源 URL 是否匹配指定的模式
    origin: (origin) => /https:\/\/(\w+\.)?myapp\.example\.com$/.test(origin),
  }),
);

未完待续...

参考资料
赞赏博主
评论 隐私政策