重构: 源码文件蛇形命名, 接口去I头(BindRequestContext/SimApiAuthChecker), 清理C#相关说明, serialization依赖路径改 serialization-cj

This commit is contained in:
2026-08-25 13:43:26 +08:00
parent 829f009229
commit 30e5f165f2
56 changed files with 319 additions and 332 deletions
+32 -32
View File
@@ -1,6 +1,6 @@
# SimApi for Cangjiesimapi
> 仓颉版 SimApiASP.NET Core 风格 API 基础框架,移植自 C# 项目 [SimApi](https://github.com/SimcuTeam/simapi-net)`E:\simcu\simapi-net`
> 仓颉版 SimApiASP.NET Core 风格 API 基础框架,移植自 [SimApi](https://github.com/SimcuTeam/simapi-net)。
提供**统一响应格式、异常拦截、Token 认证、缓存、工具集、HTTP 客户端、S3 存储、声明式注解**等 API 基础能力。
@@ -103,7 +103,7 @@ main(args: Array<String>) {
simapi-cj/
├── cjpm.toml # 包配置
├── src/
│ ├── SimApiExtensions.cj # 根包入口:SimApiExtensions 静态类(addSimApi / useSimApi + 内置路由 + 响应封装)
│ ├── simapi_extensions.cj # 根包入口:SimApiExtensions 静态类(addSimApi / useSimApi + 内置路由 + 响应封装)
│ ├── annotations/ # 声明式注解:@SimApiAuth(鉴权)、@OriginResponse(原样响应)、
│ │ # @SimApiSign(验签)、@AesBodyAES body 解密)
│ ├── authsdk/ # 认证中心 SDKSimApiAuthClient/Center/Iam + 网关中间件 + DTO
@@ -114,7 +114,7 @@ simapi-cj/
│ ├── helpers/ # SimApiError, SimApiUtil, SimApiAuth, SimApiCache, SimApiHttpClient,
│ │ # SimApiAesUtil(AES-256), SimApiSignChecker(验签), SimApiAesBodyChecker(AES body),
│ │ # SimApiStorage(S3/MinIO, 自实现 SigV4), SimApiRequestDelegateFactory, SimApiResultWriter
│ ├── interfaces/ # ISimApiAuthChecker, IBindRequestContext, SimApiSignProviderBase, AesBodyProviderBase
│ ├── interfaces/ # SimApiAuthChecker, BindRequestContext, SimApiSignProviderBase, AesBodyProviderBase
│ ├── logger/ # SimApiLogger, SimApiLoggerProvider(彩色日志)
│ ├── macros/ # ReadTomlVersion(编译期读版本号)
│ ├── middlewares/ # SimApiExceptionMiddleware, SimApiAuthMiddleware, SimApiRequestLogMiddleware
@@ -155,12 +155,12 @@ auth.logoutAll("user-001") // 退出全部
- `"localhost:6379"`(基础)
- `"localhost:6379,password=xxx"`(带密码)
- `"localhost:6379,password=xxx,db=2"`(带密码 + DB 索引)
- **InMemory 模式**:零配置,适合开发/测试;登录态带过期时间(对齐 C# 过期语义),重启后丢失
- **InMemory 模式**:零配置,适合开发/测试;登录态带过期时间,重启后丢失
- **Token 传参**Header `Token: <value>` 或 Query `token=<value>`
### 2.1 声明式鉴权 — @SimApiAuth(对齐 C# [SimApiAuth]
### 2.1 声明式鉴权 — @SimApiAuth
标注在控制器**方法或类**上,请求派发时自动执行鉴权(未登录 401 → 类型不匹配 403 → 遍历执行 `ISimApiAuthChecker`):
标注在控制器**方法或类**上,请求派发时自动执行鉴权(未登录 401 → 类型不匹配 403 → 遍历执行 `SimApiAuthChecker`):
```cangjie
import simcu::simapi.annotations.{SimApiAuth}
@@ -174,11 +174,11 @@ public class MyController <: SimApiBaseController {
}
```
> 说明:仓颉注解参数须为编译期常量,`@SimApiAuth` 支持单个类型参数(`@SimApiAuth["admin"]`)或逗号分隔多类型(`@SimApiAuth["admin,user"]`,对齐 C# `type.Split(",")`);空参数表示任意已登录用户。
> 说明:仓颉注解参数须为编译期常量,`@SimApiAuth` 支持单个类型参数(`@SimApiAuth["admin"]`)或逗号分隔多类型(`@SimApiAuth["admin,user"]`);空参数表示任意已登录用户。
### 2.2 原样响应 — @OriginResponse
标注后跳过统一响应封装,接口返回什么就输出什么(对齐 C# `[OriginResponse]`
标注后跳过统一响应封装,接口返回什么就输出什么:
```cangjie
import simcu::simapi.annotations.{OriginResponse}
@@ -190,7 +190,7 @@ public func raw(): String {
}
```
### 2.3 声明式验签 — @SimApiSign(对齐 C# [SimApiSign]
### 2.3 声明式验签 — @SimApiSign
标注在控制器**方法或类**上,请求派发时自动验签(appId 提取 → 密钥获取 → timestamp 过期校验 → nonce 去重 → MD5 比对):
@@ -210,9 +210,9 @@ public class MySignProvider <: SimApiSignProviderBase {
public func signedAction(): String { "ok" }
```
`SimApiSignProviderBase` 可配置:`appIdName` / `timestampName` / `nonceName` / `signName` / `queryExpires` / `duplicateRequestProtection` / `signFields`(与 C# 一致)。也可手动调用 `SimApiSignChecker.verify(context, provider, cache)`
`SimApiSignProviderBase` 可配置:`appIdName` / `timestampName` / `nonceName` / `signName` / `queryExpires` / `duplicateRequestProtection` / `signFields`。也可手动调用 `SimApiSignChecker.verify(context, provider, cache)`
### 2.4 声明式 AES body — @AesBody(对齐 C# [AesBody]
### 2.4 声明式 AES body — @AesBody
标注在**参数**上,请求派发时自动解密 `{"data":"密文"}` body 并反序列化为参数类型:
@@ -252,14 +252,14 @@ Key 自动加前缀 `SimApi:Cache:`。
```cangjie
SimApiUtil.cstNow // UTC+8 时间
SimApiUtil.timestampNow // 秒级时间戳
SimApiUtil.newGuid() // UUID v4(对齐 C# Guid.NewGuid()
SimApiUtil.newGuid() // UUID v4
SimApiUtil.md5("text") // 32 位十六进制
SimApiUtil.sha1("text") // 40 位
SimApiUtil.base64Encode("text") / base64Decode("...")
SimApiUtil.base64Encode(obj) // 对象 → JSON → Base64(对齐 C# Base64Encode(object)
SimApiUtil.base64Encode(obj) // 对象 → JSON → Base64
SimApiUtil.json(obj) // 对象 → JSON 字符串(simcu::serialization 反射)
SimApiUtil.escapeJson(s) // JSON 字符串转义
SimApiUtil.fromJson<T>(json) // JSON → T对齐 C# FromJson<T>任意类免约束)
SimApiUtil.fromJson<T>(json) // JSON → T(任意类免约束)
SimApiUtil.base64DecodeTo<T>(str) // Base64 → JSON → T
SimApiUtil.checkCell("13800138000") // 手机号
SimApiUtil.checkEmail("a@b.com") // 邮箱
@@ -267,9 +267,9 @@ SimApiUtil.checkEmail("a@b.com") // 邮箱
> JSON 序列化/反序列化统一走 **simcu::serialization**`JsonSerializer.Serialize` / `Deserialize<T>`),任意类免标注、免接口约束。
### 4.1 AES 加解密 — SimApiAesUtil(对齐 C# SimApiAesUtil
### 4.1 AES 加解密 — SimApiAesUtil
纯仓颉实现 AES-256-CBC + PKCS7S-box/密钥扩展/轮函数),与 .NET 双向互操作已验证:
纯仓颉实现 AES-256-CBC + PKCS7S-box/密钥扩展/轮函数),加解密结果跨语言互通已验证:
```cangjie
let encrypted = SimApiAesUtil.encrypt("明文", "key字符串") // Base64(随机IV + 密文)
@@ -279,7 +279,7 @@ let plain = SimApiAesUtil.decrypt(encrypted, "key字符串")
- 密钥:`SHA256(key 字符串)` → 32 字节;IV 每次随机 16 字节前置;输出 `Base64(IV + 密文)`
-`SimApiHttpClient.aesQuery<T>` / `aesSignQuery<T>` 使用
### 4.2 实体基类 — SimApiBaseModel(对齐 C# SimApiBaseModel
### 4.2 实体基类 — SimApiBaseModel
```cangjie
import simcu::simapi.models.*
@@ -301,19 +301,19 @@ user.updateTime() // 刷新 _updatedAt
```cangjie
let client = SimApiHttpClient(options: SimApiHttpClientOptions()) // 配置 server/appId/appKey
// 返回泛型 T对齐 .NET SignQuery<T>/AesQuery<T>/AesSignQuery<T>),T 任意类免约束
// 返回泛型 TSignQuery<T>/AesQuery<T>/AesSignQuery<T>),T 任意类免约束
let resp1 = client.signQuery<SimApiLoginItem>("/api/hello", body: "{\"a\":1}")
let resp2 = client.aesQuery<SimApiLoginItem>("/api/data", body: "{\"a\":1}")
let resp3 = client.aesSignQuery<SimApiLoginItem>("/api/data", body: "{\"a\":1}")
```
签名参数名可配置(`signName / timestampName / nonceName / appIdName / signFields`,对齐 C# 的 virtual 属性)。AES 请求体用 `SimApiOneFieldRequest<String>` 序列化为 `{"data":"密文"}`(对齐 C#
签名参数名可配置(`signName / timestampName / nonceName / appIdName / signFields`)。AES 请求体用 `SimApiOneFieldRequest<String>` 序列化为 `{"data":"密文"}`
### 5.1 请求日志 — enableRequestLog
记录每次请求的方法、URL、请求头、请求体、响应状态码、耗时与异常(对齐 C#
记录每次请求的方法、URL、请求头、请求体、响应状态码、耗时与异常:
- 请求体按 **JSON 字段级截断**(仅对超长字符串字段截断,保留结构;非 JSON 整串截断)
- 下游异常**捕获记录后重抛**(对齐 C# ExceptionDispatchInfo
- 下游异常**捕获记录后重抛**
```cangjie
SimApiExtensions.addSimApi(builder) { options =>
@@ -336,7 +336,7 @@ SimApiExtensions.addSimApi(builder) { options =>
### 5.2 日志格式 — SimApiLogger
`enableLogger`(默认 `true`)时自动使用 `SimApiLoggerProvider`,输出格式对齐 C# 原版
`enableLogger`(默认 `true`)时自动使用 `SimApiLoggerProvider`,输出格式与原版一致
```
[ 分类 ][ 时间:毫秒 ][ 级别 ]
@@ -345,7 +345,7 @@ SimApiExtensions.addSimApi(builder) { options =>
按级别着色:Debug 深紫 / Info 深青 / Warn 黄 / Error 红 / Fatal 深红。
### 5.3 存储 — SimApiStorageS3/MinIO,对齐 C# SimApiStorage
### 5.3 存储 — SimApiStorageS3/MinIO
`enableSimApiStorage = true` 时注册 `SimApiStorage`Scoped,内部自实现 AWS Signature V4,基于 stdx.net.http,无需 Minio SDK):
@@ -371,7 +371,7 @@ SimApiExtensions.addSimApi(builder) { options =>
| `fullUrl(path)` / `getUrl(path)` | 补全访问 URL`~/` 前缀依赖请求上下文) |
| `getPath(url)` | 从 URL 还原相对路径(去掉 Endpoint/Bucket 或 ServeUrl 前缀) |
> 说明:桶不存在时自动创建(对齐 C# BucketExists + MakeBucket静态守卫只执行一次);
> 说明:桶不存在时自动创建(静态守卫只执行一次);
> 预签名与上传使用 AWS SigV4HMAC-SHA256 基于 stdx SHA256 自实现),已用 AWS 官方测试向量验证签名正确。
### 6. 内置路由(UseSimApi 自动注册)
@@ -392,21 +392,21 @@ options.configureSimApiRoute { route =>
}
```
### 7. 认证后处理 Hook — ISimApiAuthChecker
### 7. 认证后处理 Hook — SimApiAuthChecker
实现后每次认证成功都会调用(配合 `@SimApiAuth` 注解或手动 `requireLogin`):
```cangjie
import simcu::simapi.interfaces.*
class MyAuthChecker <: ISimApiAuthChecker {
class MyAuthChecker <: SimApiAuthChecker {
public func run(loginItem: SimApiLoginItem, token: String): Unit {
// 认证成功后执行
}
}
```
### 8. 认证中心 SDK — AuthSDK(对齐 C# AuthSDK
### 8. 认证中心 SDK — AuthSDK
`enableSimApiAuthGate = true` 时注册 `SimApiAuthClient` / `SimApiAuthCenter` / `SimApiAuthIam` 单例并挂载网关透传中间件:
@@ -457,7 +457,7 @@ SimApiExtensions.addSimApi(builder) { options =>
options.enableCors = true // 全量 CORS
options.enableLogger = true // 控制台日志
// .NET 风格子模块配置回调(对齐 C# ConfigureSimApiXxx
// 子模块配置回调(ConfigureSimApiXxx
options.configureSimApiRoute { route =>
route.userInfoRoute = Some("/user/info") // 内置路由自定义路径
route.logoutRoute = Some("/auth/logout")
@@ -483,7 +483,7 @@ SimApiExtensions.addSimApi(builder) { options =>
## 内置控制器(MVC 写法)
simapi 提供 Spire MVC 控制器(继承 `SimApiBaseController`),`addSimApi` 自动注册内置控制器 + 自动扫描调用者包中的控制器(对齐 C# `Assembly.GetTypes()` 扫描)
simapi 提供 Spire MVC 控制器(继承 `SimApiBaseController`),`addSimApi` 自动注册内置控制器 + 自动扫描调用者包中的控制器:
| 控制器 | 路由 | 说明 |
|--------|------|------|
@@ -514,7 +514,7 @@ public class MyController <: SimApiBaseController {
## 未实现模块(选项占位)
以下 C# 原包功能因仓颉生态暂无对应库(Hangfire/MQTT/Swashbuckle),**选项保留但未实现**:
以下原包功能因仓颉生态暂无对应库(Hangfire/MQTT/Swashbuckle),**选项保留但未实现**:
| 选项 | 原功能 | 状态 |
|------|--------|------|
@@ -522,7 +522,7 @@ public class MyController <: SimApiBaseController {
| `enableSynapse` | MQTT 通信 | ❌ 未实现 |
| `enableJob` | Hangfire 任务调度 | ❌ 未实现 |
> ✅ 已实现(曾为占位):`enableSimApiStorage`S3/MinIO,自实现 AWS SigV4)、`enableSimApiAuthGate`AuthSDK 认证中心)、`SimApiAesUtil`(纯仓颉 AES-256-CBC,与 .NET 双向互操作)、`ISimApiAuthChecker`、`@SimApiSign` / `@AesBody` 声明式注解、内置路由自定义路径。
> ✅ 已实现(曾为占位):`enableSimApiStorage`S3/MinIO,自实现 AWS SigV4)、`enableSimApiAuthGate`AuthSDK 认证中心)、`SimApiAesUtil`(纯仓颉 AES-256-CBC)、`SimApiAuthChecker`、`@SimApiSign` / `@AesBody` 声明式注解、内置路由自定义路径。
---
@@ -530,7 +530,7 @@ public class MyController <: SimApiBaseController {
| 依赖 | 用途 |
|------|------|
| `soulsoft_web_http / routing / hosting` | Web 框架ASP.NET Core 仓颉移植版) |
| `soulsoft_web_http / routing / hosting` | Web 框架 |
| `soulsoft_extensions_logging` 系列 | 日志 |
| `soulsoft_extensions_injection` | 依赖注入 |
| `soulsoft_extensions_configuration` | 配置 |