Skip to content

响应

ACE 提供多种方式设置响应内容。所有方式均通过 Contextctx)对象操作,在中间件或控制器方法中均可使用。

直接返回响应体

返回字符串

控制器方法返回 String 时,框架自动将其写入响应体,并将 Content-Type 设置为 text/plain; charset=utf-8

cangjie
@Controller["/hello"]
class HelloController {
    @Get[""]
    func index(): String {
        return "Hello, ACE!"
    }
}

返回 JSON 结构体

实现 toJson(): String 方法的 structclass,框架自动将其序列化为 JSON,并将 Content-Type 设置为 application/json; charset=utf-8

cangjie
struct UserVO {
    let id: Int64
    let name: String

    func toJson(): String {
        return """{"id":${id},"name":"${name}"}"""
    }
}

@Controller["/users"]
class UserController {
    @Get["/:id"]
    func getUser(@PathParam id: Int64): UserVO {
        return UserVO(id: id, name: "Alice")
    }
}

手动操作 ctx

设置响应体

cangjie
// 设置纯文本体
ctx.body = "操作成功"

// 手动设置 JSON 体(同时更新 Content-Type)
ctx.json("""{"code":0,"msg":"ok"}""")

设置状态码

cangjie
ctx.status = 201u16   // Created
ctx.status = 204u16   // No Content
ctx.status = 404u16   // Not Found

TIP

仓颉中整数字面量需要显式后缀,状态码必须写 u16,否则类型不匹配。

设置响应头

cangjie
ctx.setHeader("X-Request-Id", "abc-123")
ctx.setHeader("Cache-Control", "no-cache")
cangjie
import ace_web.CookieOptions

let opts = CookieOptions(
    httpOnly: true,
    maxAge: 86400,   // 秒
    path: "/",
    secure: true
)
ctx.setCookie("session", "tok_xyz", opts)

CookieOptions 字段说明

字段类型默认值说明
httpOnlyBoolfalse禁止 JavaScript 访问
maxAgeInt640(会话)Cookie 有效期(秒)
pathString"/"Cookie 作用路径
secureBoolfalse仅 HTTPS 发送
sameSiteString""Strict/Lax/None
domainString""Cookie 作用域名

流式响应

对于大文件下载、SSE 等场景,使用 ctx.setStreamBody 进行分块传输(Transfer-Encoding: chunked)。

cangjie
@Get["/events"]
func sse(ctx: Context): Unit {
    ctx.setHeader("Content-Type", "text/event-stream")
    ctx.setHeader("Cache-Control", "no-cache")

    ctx.setStreamBody { write in
        for i in 0..5 {
            write("data: message ${i}\n\n")
            // 实际场景中可在此 await 异步数据源
        }
    }
}

WARNING

setStreamBody 闭包执行期间不可再设置响应头或状态码,请在调用前完成所有头部配置。

内容协商

ACE 支持按请求 Accept 头自动选择编码器。通过 registerBodyEncoder 注册自定义格式:

cangjie
import ace_web.{registerBodyEncoder, BodyEncoder}

// 注册 MessagePack 编码器(示例)
registerBodyEncoder("application/msgpack", MsgpackEncoder())

// encodeBody 根据 Accept 头自动选择
@Get["/data"]
func getData(ctx: Context): MyData {
    return encodeBody(ctx, MyData(...))
}

registerBodyEncoder 参数:

参数类型说明
mimeTypeString对应 Accept 头值
encoderBodyEncoder实现 encode(Any): String 的编码器实例

gzip 压缩

App 中挂载 gzipMiddleware 即可对响应体自动压缩:

cangjie
import ace_web.App
import ace_framework.middleware.gzipMiddleware

let app = App()
app.use(gzipMiddleware(minLength: 1024))  // 超过 1KB 才压缩

TIP

gzipMiddleware 仅压缩 text/*application/json,二进制流不会被二次压缩。

基于 Apache-2.0 许可证发布