package api import ( "reflect" "unsafe" "apigo.cc/go/cast" "apigo.cc/go/safe" ) // Action 是所有接口的基础标识接口 type Action interface { ActionName() string // 例如: "tencent.sms.send" } // SignerAction 定义需要签名的动作 type SignerAction interface { SignerName() string // 例如: "tc3" } // ConfigurableAction 定义可以提供默认硬编码配置的动作 type ConfigurableAction interface { Config() map[string]any } // URLAction 定义显式指定 URL 的动作 type URLAction interface { GetURL() string } // MethodAction 定义显式指定方法的动作 type MethodAction interface { GetMethod() string // 例如: "GET" } // ValidatableAction 定义支持自我校验的动作 type ValidatableAction interface { Validate() error } // FormatAction 定义请求体格式 type FormatAction interface { GetFormat() string // 返回: "json", "form", "multipart" } // ActionRegistry 存储已注册的 Action 模板或类型 var actionRegistry = make(map[string]any) // RegisterAction 注册 API 动作。 // definition 可以是一个结构体实例(用作类型模板)或一个 map[string]any(用作动态定义)。 func RegisterAction(name string, definition any) { if definition == nil { return } t := reflect.TypeOf(definition) for t.Kind() == reflect.Ptr { t = t.Elem() } if t.Kind() == reflect.Struct { actionRegistry[name] = t } else if m, ok := definition.(map[string]any); ok { ga := &GenericAction{ name: name, url: cast.String(m["url"]), method: cast.String(m["method"]), signer: cast.String(m["signer"]), format: cast.String(m["format"]), payload: make(map[string]any), } if p, ok := m["payload"].(map[string]any); ok { ga.payload = p } actionRegistry[name] = ga } } // GenericAction 是一个动态 Action 容器,实现了所有 API 相关接口 type GenericAction struct { name string url string method string signer string format string payload map[string]any } func (a *GenericAction) ActionName() string { return a.name } func (a *GenericAction) SignerName() string { return a.signer } func (a *GenericAction) GetURL() string { return a.url } func (a *GenericAction) GetMethod() string { return a.method } func (a *GenericAction) GetFormat() string { return a.format } func (a *GenericAction) Config() map[string]any { return map[string]any{ "url": a.url, "method": a.method, "signer": a.signer, "format": a.format, } } func (a *GenericAction) MarshalJSON() ([]byte, error) { return cast.ToJSONBytes(a.payload) } // HttpRequest 内部使用的请求描述结构,供 Signer 使用 type HttpRequest struct { Url string Method string headers map[string]string Payload any wipeableBuffers [][]byte // 追踪需要安全擦除的敏感缓冲区 } // GetHeader 获取指定 Header 的值 func (r *HttpRequest) GetHeader(key string) string { if r == nil || r.headers == nil { return "" } return r.headers[key] } // Close 物理覆盖并清除所有关联的敏感缓冲区,确保内存中不再留存明文 func (r *HttpRequest) Close() { if r == nil { return } // 擦除缓冲区 for _, buffer := range r.wipeableBuffers { safe.ZeroMemory(buffer) } r.wipeableBuffers = nil } // SetHeader 提供无感知的安全 Header 设置功能。支持传入多个参数进行自动拼接。 // 如果参数中包含 *safe.SafeBuf, *safe.SecretPlaintext 或 []byte (标记为敏感), // 整个生成的 Header 缓冲区都将被注册用于后置物理擦除。 // 安全的拼接与转换(如 safe.Concat, safe.Base64)建议使用 safe 包提供的返回 *safe.SafeBuf 的方法。 func (r *HttpRequest) SetHeader(key string, values ...any) { if len(values) == 0 { return } if r.headers == nil { r.headers = make(map[string]string) } // 1. 计算总长度并识别是否有敏感数据 totalLen := 0 isSensitive := false for _, v := range values { switch t := v.(type) { case string: totalLen += len(t) case []byte: totalLen += len(t) isSensitive = true case *safe.SafeBuf: if t == nil { continue } p := t.Open() totalLen += len(p.Data) p.Close() isSensitive = true case *safe.SecretPlaintext: if t == nil { continue } totalLen += len(t.Data) isSensitive = true default: s := cast.String(v) totalLen += len(s) } } // 2. 分配单一缓冲区进行拼接 buf := make([]byte, totalLen) pos := 0 for _, v := range values { switch t := v.(type) { case string: pos += copy(buf[pos:], t) case []byte: pos += copy(buf[pos:], t) case *safe.SafeBuf: if t == nil { continue } p := t.Open() pos += copy(buf[pos:], p.Data) p.Close() case *safe.SecretPlaintext: if t == nil { continue } pos += copy(buf[pos:], t.Data) default: pos += copy(buf[pos:], cast.String(v)) } } // 3. 映射到 headers 并注册清理 r.headers[key] = unsafe.String(&buf[0], len(buf)) if isSensitive { r.wipeableBuffers = append(r.wipeableBuffers, buf) } } // Result 定义 API 调用的标准返回结果 type Result struct { StatusCode int Status string Headers map[string]string Data any }