第 3 卷
18this.matcher = ctx.re2// 它自己还消费 re2(正则匹配器)
19} 20}
21 22// Consumer(ingress-authz.ts)——只认契约
23export class IngressAuthz extends Service { 24static inject = ['firewall'] as const
25 26constructor(ctx: Context) {
27super(ctx, 'ingressAuthz')
28} 29// authorize(request):先查超长,再交给 this.ctx.firewall.evaluate(request)
30} 31
第二步:插件装配。下面这个插件在自己的 apply 里挂了两个子插件,SafeRe2Matcher 和 FirewallEngine,分别提供 re2 和 firewall 两个能力:
复制代码 1// firewall-plugin.ts —— dsh 插件
2export const name = 'firewall' 3
| 4 | exportfunctionapply(ctx: Context):void{ |
|---|---|
| 5 | ctx.plugin(SafeRe2Matcher) |
| 6 | ctx.plugin(FirewallEngine) |
| 7 | } |
引擎怎样从本地启动到生产部署:profile、bundle、patch
dsh 启动一次,就是按“组合清单 → 组合包 → patch 层”的顺序依次用到这三样。先读清单知道装什么,再按名字找到组合包,取它的 patch。下面照这个顺序认识它们,每个都配上真
实的配置文件。
组合清单(profile):$DSH_HOME/profiles/<name>/</name> 下的目录,回答“这次启
先看 package.json:
复制代码 1{
2"name": "dsh-profile-demo", 3"dsh": {
4"profile": {
| 5 | "bundles": ["@deepseek-ai/dsh-base","dsh-firewall-rule"] |
|---|---|
| 6 | } |
| 7 | } |
| 8 } |
组合包(bundle):一个打包好的 npm 包,里面装着两样东西:插件代码本身,和一份 patch 文件。
为什么这两样要打包在一起?因为 patch 只写了“挂哪些插件、覆盖哪些配置”,它指向的代码得由这个包提供,两者合成一个 npm 包,这份能力才能被发布、被别人 dsh plugin
add 装走。下面这份 package.json 里,name 是包的名字,安装、引用都用这个,main 指向代码入口,dsh.bundle.patch 指向那份 patch 文件:
复制代码 1{
2"name": "dsh-firewall-rule", 3"main": "lib/index.js",
4"dsh": { 5"bundle": {
6"patch": "./cordis.patch.yml"
7} 8}
9}
调它的 apply,把 re2 匹配器、防火墙引擎、拦请求的入口、只读工具依次挂上树;
cordis.patch.yml 则是启动这次挂载的那份配置。
patch 层:按 id 定位某条目、整行替换它的 config,或用 insert 添加新条目。同一个 patch 机制有三个来源:bundle 自带的、profile 里用户自己的、命令行 --patch 给的,这
第三种叫 overlay,下面“开发调试”用的就是它。语法完全一样,区别只在叠放的先后,你可以看下面讲的层叠规则。
组合包自带的 patch 长这样:
复制代码
| 1 | # packages/dsh-firewall-rule/cordis.patch.yml |
|---|---|
| 2 | - insert: |
| 3 | -id: firewall #条目id,后面的patch就按它定位 |
| 4 | name:'dsh-firewall-rule' #从哪加载这个插件:这里写包名(与上面package.json的 |
这一讲里这份用的是 insert,新增一行;没写 config,因为这个插件不需要配置项。
这份 patch 里两个字段容易混:id 与 name。
id 回答“改哪一行”:改已有条目的配置只给 id + config,也就是按 id 定位、整行替换,此时不写 name,写了就表示连插件模块一起换掉。
patch 里的 name 回答“这一行加载谁”,可写包名或相对路径。它和 package.json 的 name,即“这个包叫什么”,通常相同,但那只是“这个包只装自己这一个插件”的结果,
name 也可以写别人的包名。
profile、bundle、patch 这三样都是“声明”,真正执行它们的是 dsh,合起来就是一次启动的完整过程: