Seagull (海鸥)

基于 swift-nio 的快速 Web 框架。

Seagull 的主要思想是创建一个最小化的 Web 框架。 仅包含路由和一些数据处理辅助工具。 Seagull 的灵感来自 gin-gonic,我最喜欢的 Golang Web 框架。 轻量级,易于使用,最小的功能集,但速度非常快。

新闻

项目已更新至 0.2.5 版本。 主要特性是全新的、更快的 Router。 https://github.com/gavrilaf/SgRouter

开始使用

构建并启动测试 REST 服务器。

swift run SeagullRestDemo

或使用 make

make run-rest 

运行基本 rest 服务器实现的集成测试

make ptest

使用 docker-compose 运行

运行单元测试

docker-compose -f docker/docker-compose.yaml up unit-tests

运行 Rest 服务器示例

docker-compose -f docker/docker-compose.yaml up rest

API 示例

var router = HttpRouter()
try router.GET("/", handler: Handlers.ping)
try router.GET("whoami", handler: Handlers.whoami, with: [Handlers.tokenMiddleware])
    
let engine = Engine(router: router)
try engine.run(host: host, port: port)
    
defer { try! engine.close() }
try engine.waitForCompletion()

路径中的参数

try router.GET("/profile/shared/:username", handler: Handlers.getProfile)

static func getProfile(_ request: SgRequest, _ ctx: SgRequestContext) -> SgResult {
  do {
    guard let username = request.urlParams["username"] else { throw AppLogicError.invalidParam }
    let profile = try Db.inst.getProfile(username: username)
    .....
  } catch let err {
    return ctx.error(err)
  }
}

查询字符串参数

try router.GET("/withParams", handler: { (req, ctx) -> SgResult in
  let p1 = req.queryParams["paramOne"] ?? "not-found"
  let p2 = req.queryParams["paramTwo"] ?? "not-found"
  .....
}

.../withParams?paramOne=abc&paramTwo=100

路由分组

try router.group("/auth") {
    try $0.PUT("/register", handler: Handlers.register)
    try $0.POST("/login", handler: Handlers.login)
}

使用中间件

try router.group("/profile", middleware: [Handlers.tokenMiddleware, logMiddleware, ...]) {
  try $0.GET("/", handler: Handlers.getMyProfile)
  try $0.POST("/", handler: Handlers.updateProfile)
  try $0.DELETE("/", handler: Handlers.deleteProfile)
}

中间件处理程序将在主处理程序之前按传递顺序调用。

捕获所有参数

let siteContentHandler: RequestHandler = { (req, ctx) in
    let pathParam = req.urlParams["path"]!
    let path = FileManager.default.currentDirectoryPath + "/html/" + pathParam
    return SgResult.file(response: SgFileResponse(path: path, headers: mimeType))
}
........
try router.GET("/site/*path", handler: siteContentHandler)
........

.../site/index.html
.../site/images/logo.jpg

项目正在积极开发中,尚未准备好用于生产环境。 但它非常适合实验 :)

当前版本为 0.2.5