2026-09-01 18:17:37 +08:00
2026-09-01 18:17:37 +08:00
2026-09-01 18:17:37 +08:00
2026-09-01 18:17:37 +08:00
2026-09-01 18:17:37 +08:00
2026-09-01 18:17:37 +08:00
2026-09-01 18:17:37 +08:00

SimApi for Cangjiesimapi

仓颉版 SimApiASP.NET Core 风格 API 基础框架,移植自 SimApi

提供统一响应格式、异常拦截、Token 认证、缓存、工具集、HTTP 客户端、S3 存储、声明式注解、OpenAPI 文档等 API 基础能力。


引入

两种方式任选其一:

方式一:中央仓(需先 cjpm publish 发布 simcu::simapi

[dependencies]
"simcu::simapi" = "1.0.3"

方式二:Git 仓库

[dependencies]
"simcu::simapi" = { git = "https://gitcode.com/simcu/simapi-cj.git", version = "1.0.3" }

本地开发也可用 path 依赖:"simcu::simapi" = { path = "../simapi-cj" }


快速开始

package your_app

import soulsoft_web_http.*
import soulsoft_web_routing.*
import soulsoft_web_hosting.*
import soulsoft_extensions_logging.*
import soulsoft_extensions_injection.*
import simcu::simapi.*
import simcu::simapi.communications.*
import simcu::simapi.helpers.*

main(args: Array<String>) {
    let builder = WebHost.createBuilder(args)
    builder.services.addRouting()
    builder.services.addLogging()

    // 注册 SimApi 服务(与 addLogging 同样式)
    SimApiExtensions.addSimApi(builder) { options =>
        options.enableSimApiAuth = true     // Token 认证(未配 Redis 自动用 InMemory
        options.enableSimApiCache = true    // 缓存
        options.enableSimApiException = true // 全局异常拦截
    }

    let host = builder.build()
    SimApiExtensions.useSimApi(host)

    // 业务接口:返回对象自动封装为统一响应格式({code, message, data}
    host.mapGet("hello") {
        context =>
            context.response.write(SimApiUtil.json(Some(SimApiResponse<String>("hello cangjie."))))
    }

    host.run()
}

统一响应格式

所有接口输出 JSON,HTTP 状态码始终 200,错误信息在 code 字段:

code 含义
200 成功
204 无数据
400 参数错误
401 需要登录
403 无权访问
404 资源不存在
500 服务器错误

响应 JSON(经 simcu::serialization 反射序列化,字段无下划线):

{ "code": 200, "message": "成功", "data": { ... } }

异常处理流程

请求 → SimApiExceptionMiddleware(全异常捕获→HTTP 200+JSON)
     → SimApiAuthMiddleware(Token→LoginInfo)
     → 路由 → 业务处理

项目结构

simapi-cj/
├── cjpm.toml                  # 包配置
├── src/
│   ├── simapi_extensions.cj   # 根包入口:SimApiExtensions 静态类(addSimApi / useSimApi + 内置路由 + 响应封装)
│   ├── annotations/           # 声明式注解:@SimApiAuth(鉴权)、@OriginResponse(原样响应)、
│   │                          #   @SimApiSign(验签)、@AesBodyAES body 解密)
│   ├── authsdk/               # 认证中心 SDKSimApiAuthClient/Center/Iam + 网关中间件 + DTO
│   ├── communications/        # SimApiBaseResponse, PageResponse, SimApiLoginItem, 请求 DTO
│   ├── configurations/        # SimApiOptions + 各模块 Option(含 ConfigureSimApiXxx 回调)
│   ├── controllers/           # SimApiBaseController, SimApiCommonController, SimApiAuthControllerMVC 写法)
│   ├── exceptions/            # SimApiException
│   ├── helpers/               # SimApiError, SimApiUtil, SimApiAuth, SimApiCache, SimApiHttpClient,
│   │                          #   SimApiAesUtil(AES-256), SimApiSignChecker(验签), SimApiAesBodyChecker(AES body),
│   │                          #   SimApiStorage(S3/MinIO, 自实现 SigV4), SimApiRequestDelegateFactory, SimApiResultWriter
│   ├── interfaces/            # SimApiAuthChecker, BindRequestContext, SimApiSignProviderBase, AesBodyProviderBase
│   ├── logger/                # SimApiLogger, SimApiLoggerProvider(彩色日志)
│   ├── macros/                # ReadTomlVersion(编译期读版本号)、EnumString(枚举字符串双向转换)
│   ├── middlewares/           # SimApiExceptionMiddleware, SimApiAuthMiddleware, SimApiRequestLogMiddleware
│   ├── models/                # SimApiBaseModel(实体基类)
│   └── openapi/               # OpenAPI 文档生成 + Swagger UI 内置资源
│       ├── annotations/       # @SimApiDoc(文档元数据注解)
│       ├── metadata/          # IApiGroupNamesProvider, IApiResponseTypeMetadata 等元数据接口
│       ├── models/            # OpenApiDocument, OpenApiSchema, OpenApiInfo 等 OpenAPI 模型
│       ├── services/          # OpenApiDocumentService(文档生成), OpenApiSchemaService, OpenApiOptions
│       └── infrastructure/    # OpenApiConstants

模块说明

1. 错误处理 — SimApiError

import simcu::simapi.helpers.*

SimApiError.error(500, "服务器内部错误")          // 直接抛错
SimApiError.errorWhen(amount <= 0, 400, "金额无效") // 条件为 true 时抛错
SimApiError.errorWhenFalse(hasPermission, 403, "无权操作")
SimApiError.errorWhenNull(someOptional, 404, "用户不存在")

2. 认证 — SimApiAuth

import simcu::simapi.helpers.*
import simcu::simapi.communications.*

// 由 DI 注入(构造参数 options: SimApiOptions,从配置读 RedisConfiguration;未配则 InMemory
let auth: SimApiAuth = ...   // 例:控制器构造注入

let token = auth.login(SimApiLoginItem(id: "user-001"))  // 默认 7 天
let login = auth.getLogin(token)                // 获取登录信息
auth.logout(token)                              // 退出登录
auth.logoutAll("user-001")                      // 退出全部
  • Redis 模式:配置 RedisConfiguration 时使用,支持多实例共享。连接串格式:
    • "localhost:6379"(基础)
    • "localhost:6379,password=xxx"(带密码)
    • "localhost:6379,password=xxx,db=2"(带密码 + DB 索引)
  • InMemory 模式:零配置,适合开发/测试;登录态带过期时间,重启后丢失
  • Token 传参Header Token: <value> 或 Query token=<value>

2.1 声明式鉴权 — @SimApiAuth

标注在控制器方法或类上,请求派发时自动执行鉴权(未登录 401 → 类型不匹配 403 → 遍历执行 SimApiAuthChecker):

import simcu::simapi.annotations.{SimApiAuth}

@SimApiAuth                    // 类级:整个控制器需登录
public class MyController <: SimApiBaseController {

    @SimApiAuth["admin"]       // 方法级:仅 admin 类型可访问
    @HttpPost["my/admin-only"]
    public func adminOnly(): String { "ok" }
}

说明:仓颉注解参数须为编译期常量,@SimApiAuth 支持单个类型参数(@SimApiAuth["admin"])或逗号分隔多类型(@SimApiAuth["admin,user"]);空参数表示任意已登录用户。

2.2 原样响应 — @OriginResponse

标注后跳过统一响应封装,接口返回什么就输出什么:

import simcu::simapi.annotations.{OriginResponse}

@OriginResponse
@HttpGet["raw"]
public func raw(): String {
    "{\"raw\":true}"   // 直接输出,不包 {code,message,data}
}

2.3 声明式验签 — @SimApiSign

标注在控制器方法或类上,请求派发时自动验签(appId 提取 → 密钥获取 → timestamp 过期校验 → nonce 去重 → MD5 比对):

import simcu::simapi.annotations.{SimApiSign}
import simcu::simapi.interfaces.{SimApiSignProviderBase}

// 1. 继承 Provider 实现密钥获取(并注册到 DI
public class MySignProvider <: SimApiSignProviderBase {
    public override func getKey(appId: ?String): ?String {
        Some("my-secret-key")
    }
}

// 2. 方法标注 @SimApiSign,自动验签(provider 类型名从 DI 解析)
@SimApiSign["MySignProvider"]
public func signedAction(): String { "ok" }

SimApiSignProviderBase 可配置:appIdName / timestampName / nonceName / signName / queryExpires / duplicateRequestProtection / signFields。也可手动调用 SimApiSignChecker.verify(context, provider, cache)

2.4 声明式 AES body — @AesBody

标注在参数上,请求派发时自动解密 {"data":"密文"} body 并反序列化为参数类型:

import simcu::simapi.annotations.{AesBody}
import simcu::simapi.interfaces.{AesBodyProviderBase}

public class MyAesProvider <: AesBodyProviderBase {
    public override func getKey(appId: ?String): ?String {
        Some("aes-secret-key")
    }
}

public func create(@AesBody["MyAesProvider"] request: CreateRequest): String {
    // request 已自动解密并反序列化
    "ok"
}

也可手动调用 SimApiAesBodyChecker.decryptBody(context, provider) 获取明文 JSON 字符串。

3. 缓存 — SimApiCache

// 由 DI 注入(构造参数 options: SimApiOptions
let cache: SimApiCache = ...
cache.set("key", "value")
let v = cache.get("key")       // ?String
cache.hasKey("key")            // Bool
cache.remove("key")

Key 自动加前缀 SimApi:Cache:

4. 工具集 — SimApiUtil

SimApiUtil.cstNow            // UTC+8 时间
SimApiUtil.timestampNow      // 秒级时间戳
SimApiUtil.newGuid()         // UUID v4
SimApiUtil.md5("text")       // 32 位十六进制
SimApiUtil.sha1("text")      // 40 位
SimApiUtil.base64Encode("text") / base64Decode("...")
SimApiUtil.base64Encode(obj) // 对象 → JSON → Base64
SimApiUtil.json(obj)         // 对象 → JSON 字符串(simcu::serialization 反射)
SimApiUtil.escapeJson(s)     // JSON 字符串转义
SimApiUtil.fromJson<T>(json) // JSON → T(任意类免约束)
SimApiUtil.base64DecodeTo<T>(str)  // Base64 → JSON → T
SimApiUtil.checkCell("13800138000")   // 手机号
SimApiUtil.checkEmail("a@b.com")      // 邮箱

JSON 序列化/反序列化统一走 simcu::serializationJsonSerializer.Serialize / Deserialize<T>),任意类免标注、免接口约束。

4.1 AES 加解密 — SimApiAesUtil

纯仓颉实现 AES-256-CBC + PKCS7S-box/密钥扩展/轮函数),加解密结果跨语言互通已验证:

let encrypted = SimApiAesUtil.encrypt("明文", "key字符串")   // Base64(随机IV + 密文)
let plain = SimApiAesUtil.decrypt(encrypted, "key字符串")
  • 密钥:SHA256(key 字符串) → 32 字节;IV 每次随机 16 字节前置;输出 Base64(IV + 密文)
  • SimApiHttpClient.aesQuery<T> / aesSignQuery<T> 使用

4.2 实体基类 — SimApiBaseModel

import simcu::simapi.models.*

public class User <: SimApiBaseModel {
    public var _name: String = ""
}

let user = User()                       // _id 自动 GUID、_createdAt/_updatedAt 自动当前时间
user.mapData(source)                    // 反射映射:源对象同名同类型字段 → this(忽略 Id/CreatedAt/UpdatedAt
user.mapData(source, ["_name"])         // 白名单映射
user.updateTime()                       // 刷新 _updatedAt

5. HTTP 客户端 — SimApiHttpClient

用于调用其他带签名/AES 的 SimApi 服务(基于 stdx.net.http,不依赖 soulsoft_net_http;内置 TLShttps 自动配置信任所有证书 + SNI):

let client = SimApiHttpClient(options: SimApiHttpClientOptions())  // 配置 server/appId/appKey

// 返回泛型 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)。AES 请求体用 SimApiOneFieldRequest<String> 序列化为 {"data":"密文"}

5.1 请求日志 — enableRequestLog

记录每次请求的方法、URL、请求头、请求体、响应状态码、耗时与异常:

  • 请求体按 JSON 字段级截断(仅对超长字符串字段截断,保留结构;非 JSON 整串截断)
  • 下游异常捕获记录后重抛
SimApiExtensions.addSimApi(builder) { options =>
    options.enableRequestLog = true
    options.simApiRequestLogOptions.showFullHeader = true   // 打印完整 Header(默认只打 Token/Query-Id
    options.simApiRequestLogOptions.requestStringLogLength = 200  // 请求体字段截断长度(0 不截断)
}

输出示例:

[GET] /hello
*( RequestHeaders [Full] ) =>
{"host":"127.0.0.1:5000",...}
*( RequestBody ) =>
{"name":"AAAA...(200)","image":"x"}
*( Response [200] ) => 1.756400ms

5.2 日志格式 — SimApiLogger

enableLogger(默认 true)时自动使用 SimApiLoggerProvider,输出格式与原版一致:

[ 分类 ][ 时间:毫秒 ][ 级别 ]
消息内容

按级别着色:Debug 深紫 / Info 深青 / Warn 黄 / Error 红 / Fatal 深红。

5.3 存储 — SimApiStorageS3/MinIO

enableSimApiStorage = true 时注册 SimApiStorageScoped,内部自实现 AWS Signature V4,基于 stdx.net.http,无需 Minio SDK):

SimApiExtensions.addSimApi(builder) { options =>
    options.enableSimApiStorage = true
    options.configureSimApiStorage { storage =>
        storage.endpoint = "http://192.168.0.2:9000"   // 必须 http:// 或 https:// 开头
        storage.serveUrl = "https://files.example.com" // 文件访问地址,不能以 / 结尾
        storage.bucket = "app-files"
        storage.accessKey = "minioadmin"
        storage.secretKey = "minioadmin"
    }
}
方法 说明
getUploadUrl(path, expire=7200) 上传预签名 URL,返回 GetUploadUrlResponse(UploadUrl, DownloadUrl, Path)
getDownloadUrl(path, expire=600) 下载预签名 URL
uploadFile(path, data, contentType="image/png") 直接 PUT 上传(字节数组)
deleteFiles(paths) 批量删除对象(S3 原生 DeleteObjects,一次请求删多个)
fullUrl(path) / getUrl(path) 补全访问 URL~/ 前缀依赖请求上下文)
getPath(url) 从 URL 还原相对路径(去掉 Endpoint/Bucket 或 ServeUrl 前缀)

说明:桶不存在时自动创建(静态守卫只执行一次); 预签名与上传使用 AWS SigV4HMAC-SHA256 基于 stdx SHA256 自实现),已用 AWS 官方测试向量验证签名正确。

6. 内置路由(UseSimApi 自动注册)

路由 方法 条件 说明
/user/info POST enableSimApiAuth 需登录,返回 LoginInfo
/auth/logout POST enableSimApiAuth 退出登录
/exception/{code} GET 始终 错误反馈(抛 SimApiException,不出现在文档中)

路由路径可自定义(configureSimApiRoute):

options.configureSimApiRoute { route =>
    route.userInfoRoute = Some("/my/user/info")   // 自定义路径生效
    route.logoutRoute = Some("/my/auth/logout")
    route.webConfigRoute = Some("/my/config")
}

7. 认证后处理 Hook — SimApiAuthChecker

实现后每次认证成功都会调用(配合 @SimApiAuth 注解):

import simcu::simapi.interfaces.*

class MyAuthChecker <: SimApiAuthChecker {
    public func run(loginItem: SimApiLoginItem, token: String): Unit {
        // 认证成功后执行
    }
}

8. 认证中心 SDK — AuthSDK

enableSimApiAuthGate = true 时注册 SimApiAuthClient / SimApiAuthCenter / SimApiAuthIam 单例并挂载网关透传中间件:

SimApiExtensions.addSimApi(builder) { options =>
    options.enableSimApiAuthGate = true
    options.configureSimApiAuthCenter { auth =>
        auth.server = "https://auth.example.com"
        auth.appId = "app-id"
        auth.appKey = "app-key"
    }
}
说明
SimApiAuthClient SimApiHttpClient 子类,凭证取 AuthCenterOptions
SimApiAuthCenter 群组/Profile/内部应用/系统登录/安全验证等 12 个接口 + VerifySign
SimApiAuthIam 注册权限 / 获取权限标识 / 校验权限(无权限抛 403)
SimApiAuthCenterMiddleware 网关透传:X-SimApi-Gate-Auth/Time/Sign 三头 MD5 校验 → Base64 解码 LoginInfo
import simcu::simapi.authsdk.*

let center = SimApiAuthCenter(client)     // client 从 DI 注入
let groups = center.groupRelated(profileId)          // 群组列表
let loginInfo = center.getLoginInfo(code)            // 登录信息(场景校验)
let iam = SimApiAuthIam(client)
iam.checkPermission(profileId, "app:create")         // 无权限抛 403

OpenAPI 文档 — enableSimApiDoc

enableSimApiDoc = true 时自动生成 OpenAPI 3.0 JSON 文档并内置 Swagger UI 静态资源(无需外部文件,打包后不失效)。

文档分组

支持多个文档组,未标注 @SimApiDoc 的接口默认进入默认组文档:

SimApiExtensions.addSimApi(builder) { options =>
    options.enableSimApiDoc = true
    options.configureSimApiDoc { doc =>
        doc.apiGroups.add(SimApiDocGroup("api", name: "App接口", description: "对接App相关接口"))
        doc.apiGroups.add(SimApiDocGroup("admin", name: "后台管理接口", description: "后台管理接口"))
    }
}
  • SimApiDocGroup(id, name!, description!, isDefault!)name 默认取 id
  • distinctGroups():按 id 去重,用户配置覆盖默认值(保留最后出现)
  • 若所有组均未标记 isDefault,第一个组视为默认组

@SimApiDoc 注解

import simcu::simapi.openapi.annotations.*

@SimApiDoc[tags: "登录", summary: "用户登录"]
@SimApiDoc[tags: "认证", summary: "后台登录", groupNames: "admin"]
@SimApiDoc[tags: "公共", groupNames: "api,admin"]   // 同时出现在 api 和 admin 文档
@SimApiDoc[tags: "公共", groupNames: "*"]            // 出现在所有文档
@SimApiDoc[ignore: true]                             // 不出现在文档中
  • groupNames:逗号分隔多个组名,* 表示所有文档,空串表示未分组(仅进默认文档)
  • ignore: true:从文档中隐藏

路由前缀

options.configureSimApiDoc { doc =>
    doc.urlPrefix = "docs"   // 默认值,可自定义
}
路由 说明
/{prefix}/all.html 多文档切换页(顶部栏下拉选择所有文档)
/{prefix}/{id}.html 单文档页(无顶部栏,自动加载 {id}.json
/{prefix}/urls 文档列表 JSON(供 Swagger UI 下拉)
/{prefix}/{id}.json OpenAPI 文档 JSON

Swagger UI 静态资源(CSS/JS/HTML)以 Base64 内联编译,运行时由 OpenApiUIMiddleware 解码输出。资源更新后运行 pwsh tools/gen-swagger-ui-resources.ps1 重新生成。

响应封装与文档

接口返回值自动封装为统一响应格式,文档中 response schema 也体现封装

返回类型 @OriginResponse 文档 response schema
SimApiBaseResponse/SimApiResponse<T>/SimApiDataResponse - 原样不封装
任意类型 原样不封装
Unit (void) {code: int64, message: string}
String {code, message, data: {type: string}}
DTO {code, message, data: {$ref: DTO}}

认证锁图标

仅标注了 @SimApiAuth 的接口在文档中显示锁图标(operation 级 security),未标注的接口不显示。

动态注册的路由(lambda)需用 withSimApiAuth 扩展方法手动添加认证元数据:

host.mapPost(route, { context => ... })
    .withOpenApi(SimApiDoc(tags: "认证", summary: "获取用户信息"))
    .withSimApiAuth(SimApiAuth())
    .withResponseType(TypeInfo.of<SimApiLoginItem>())
  • withSimApiAuth:添加 @SimApiAuth 元数据(显示锁图标)
  • withResponseType:添加响应类型元数据(动态路由无 ControllerActionDescriptor,需手动指定返回类型才能生成 response schema

EnumString — 枚举字符串双向转换

仓颉 1.1.3 枚举没有默认 ToString,且字符串插值要求实现 ToString 接口(见 RULE.MD §6.5)。在枚举声明上标注 @EnumString,编译期自动在枚举体外生成 extend,提供纯成员名的双向转换:

import simcu::simapi.macros.*

@EnumString
public enum AssetKind {
    | Passport
    | Package
}

// 生成(示意):
// extend AssetKind <: ToString {
//     public func toString(): String { ... }                 // "Passport" / "Package"
//     public static func fromString(s: String): AssetKind    // 反查,未匹配抛 Exception
// }

let kind = AssetKind.fromString("Passport")  // AssetKind.Passport
let s = "${kind}"                            // "Passport"
// AssetKind.fromString("Unknown")            // 抛 Exception: AssetKind.fromString: 未知枚举值 'Unknown'
  • @Derive[ToString] 的区别:Derive 输出带类型名前缀(Kind.A),本宏输出纯成员名,适合写库 / 读库还原 / 字符串插值。
  • 仅支持纯无参构造器枚举;带参数构造器、...non-exhaustive)在编译期直接报错。
  • 生成的是普通 extend零运行时开销match 穷尽构造器,无反射)。

ReadTomlVersion — 编译期读版本号

读取 cjpm.toml 的 version 字段并替换变量声明,用于把版本号写进响应头等场景:

import simcu::simapi.macros.*

@ReadTomlVersion[path: "cjpm.toml"]
let appVersion: String = ""

@ReadTomlVersion[path: "../simapi-cj/cjpm.toml"]   // 读取其他包版本
let simApiVersion: String = ""

SimApiOptions 完整配置

SimApiExtensions.addSimApi(builder) { options =>
    options.redisConfiguration = "localhost:6379"  // Redis(可选,支持 ,password=xxx,db=2

    // 功能开关
    options.enableSimApiAuth       = false   // Token 认证
    options.enableSimApiCache      = true    // 缓存
    options.enableSimApiException  = true    // 全局异常拦截
    options.enableSimApiResponseFilter = true // 响应统一封装
    options.enableSimApiHttpClient = false   // HTTP 客户端
    options.enableSimApiAuthGate   = false   // 认证中心 SDK + 网关中间件
    options.enableSimApiDoc        = false   // OpenAPI 文档 + Swagger UI
    options.enableRequestLog       = false   // 请求日志中间件
    options.enableCors             = true    // 全量 CORS
    options.enableLogger           = true    // 控制台日志

    // 子模块配置回调(ConfigureSimApiXxx
    options.configureSimApiRoute { route =>
        route.userInfoRoute = Some("/user/info")   // 内置路由自定义路径
        route.logoutRoute = Some("/auth/logout")
        route.webConfigRoute = Some("/config")
    }
    options.configureSimApiDoc { doc =>
        doc.urlPrefix = "docs"                      // 文档路由前缀(默认 "docs"
        doc.apiGroups.add(SimApiDocGroup("api", name: "App接口", description: "App接口文档"))
        doc.apiGroups.add(SimApiDocGroup("admin", name: "后台管理", description: "后台管理接口"))
    }
    options.configureSimApiRequestLog { opt =>
        opt.showFullResponse = true
        opt.showFullHeader = false
        opt.requestStringLogLength = 50
    }
    options.configureSimApiHttpClient { http =>
        http.appId = "your-app-id"
        http.appKey = "your-app-key"
        http.server = "https://api.example.com"
    }
    options.configureSimApiAuthCenter { auth =>
        auth.server = "https://auth.example.com"
        auth.appId = "auth-app-id"
        auth.appKey = "auth-app-key"
    }
}

内置控制器(MVC 写法)

simapi 提供 Spire MVC 控制器(继承 SimApiBaseController),addSimApi 自动注册内置控制器 + 自动扫描调用者包中的控制器:

控制器 路由 说明
SimApiCommonController /exception/{code}/config/user/info 通用内置路由
SimApiAuthController /auth/logout 退出登录
SimApiBaseController 基类:loginInfo / loginToken(访问时自动校验登录,未登录抛 401)
import simcu::simapi.controllers.*
import simcu::simapi.annotations.{SimApiAuth}

// 控制器写法:继承 SimApiBaseController,注解路由 + DI 注入
@SimApiAuth                    // 类级鉴权
public class MyController <: SimApiBaseController {
    private let _auth: SimApiAuth
    public init(auth: SimApiAuth) { this._auth = auth }

    @HttpPost["my/route"]
    public func myAction(@FromBody request: MyRequest): String {
        "ok"
    }
}

宿主无需手动注册控制器:builder.addSimApi {} 内部自动扫描并注册。


未实现模块(选项占位)

以下原包功能因仓颉生态暂无对应库(Hangfire/MQTT),选项保留但未实现

选项 原功能 状态
enableSynapse MQTT 通信 未实现
enableJob Hangfire 任务调度 未实现

已实现(曾为占位):enableSimApiDocOpenAPI 文档 + Swagger UI)、enableSimApiStorageS3/MinIO,自实现 AWS SigV4)、enableSimApiAuthGateAuthSDK 认证中心)、SimApiAesUtil(纯仓颉 AES-256-CBC)、SimApiAuthChecker@SimApiSign / @AesBody 声明式注解、内置路由自定义路径。


依赖

依赖 用途
soulsoft_web_http / routing / hosting Web 框架
soulsoft_extensions_logging 系列 日志
soulsoft_extensions_injection 依赖注入
soulsoft_extensions_configuration 配置
simcu::serializationpath 依赖) JSON 序列化(simapi 自研,反射免标注)
redispkg.cangjie-lang.cn Redis 客户端(认证/缓存 Redis 模式)
stdxCANGJIE_STDX_PATH 标准扩展库(md5/sha1/base64/http/tls
soulsoft_web_mvc MVC 框架(控制器路由、模型绑定)

构建前需设置 CANGJIE_STDX_PATH 指向本地 stdx 的 static/stdx 目录。 OpenAPI Swagger UI 静态资源内置(Base64 内联),更新资源后运行 pwsh tools/gen-swagger-ui-resources.ps1


许可证

MIT

S
Description
仓颉版 SimApi:ASP.NET Core 风格 API 基础框架,移植自 C# 项目
Readme
1.9 MiB
Languages
Cangjie 65.8%
JavaScript 34.1%