仓库里的 libs/entitlement/pluginprovider/fake.go(FakePlugin)就是协议服务端的参考实现:验签、时间窗、nonce、幂等、签名应答和沙箱行为都在里面。上面的协议节示例由它改写:
func (p *Plugin) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// {base_url}/cdnca-provider/v1/{kind}/{action}
i := strings.Index(r.URL.Path, "/cdnca-provider/v1/")
kind, action, _ := strings.Cut(r.URL.Path[i+len("/cdnca-provider/v1/"):], "/")
nonce := r.Header.Get("X-Cdnca-Provider-Nonce")
body, _ := io.ReadAll(io.LimitReader(r.Body, 256<<10))
ts := r.Header.Get("X-Cdnca-Provider-Timestamp")
unix, err := strconv.ParseInt(ts, 10, 64)
sig, _ := base64.RawURLEncoding.DecodeString(r.Header.Get("X-Cdnca-Provider-Signature"))
skew := time.Now().Unix() - unix
msg := "cdnca-provider-request/v1\n" + r.Header.Get("X-Cdnca-Provider-Installation") + "\n" + p.PluginID +
"\n" + kind + "\n" + action + "\n" + ts + "\n" + nonce + "\n" + sha256hex(body)
if i < 0 || err != nil || len(nonce) != 32 || skew > 300 || skew < -300 || p.seen(nonce) ||
!ed25519.Verify(p.InstallationKey, []byte(msg), sig) {
p.reply(w, kind, action, nonce, 401, "unauthorized", nil)
return
}
// … 按 kind/action 处理,写操作按 idempotency_key 去重 …
p.reply(w, kind, action, nonce, 200, "", map[string]any{})
}
func (p *Plugin) reply(w http.ResponseWriter, kind, action, nonce string, status int, code string, data any) {
env := map[string]any{"protocol": "cdnca.provider/v1", "ok": code == ""}
if code != "" {
env["error"] = map[string]string{"code": code}
}
if data != nil {
env["data"] = data
}
body, _ := json.Marshal(env)
msg := "cdnca-provider-response/v1\n" + p.PluginID + "\n" + kind + "\n" + action + "\n" + nonce + "\n" + sha256hex(body)
w.Header().Set("Content-Type", "application/json")
w.Header().Set("X-Cdnca-Provider-Response-Signature",
base64.RawURLEncoding.EncodeToString(ed25519.Sign(p.ResponseKey, []byte(msg))))
w.WriteHeader(status)
w.Write(body)
}
主控安装时跑的契约用例(RunContract,contract.go):所有 kind 都有 verify、rejects_bad_signature、rejects_tampered_body、rejects_stale_timestamp、rejects_replayed_nonce;dns 另有 create_a、list_created、create_idempotent、update_a、delete_a、delete_missing_not_found、txt_line、unknown_zone;sms 有 send、send_idempotent、invalid_number;mail 有 health、send、send_idempotent、invalid_recipient;icp 有 filed、unfiled、invalid_domain;payment 有 create_checkout、query_unpaid、sandbox_settle、query_paid、verify_callback、rejects_tampered_callback、refund_idempotent、refund_over_limit、reconcile、unknown_order。本地可以仿照 pluginprovider_test.go 的 newHarness,把 pluginprovider.NewClient 指向你的服务后调用 pluginprovider.RunContract,看到的结果与客户主控一致。