这是一个 Swift Package,它使用 result builder 在 Vapor 框架之上构建一个 DSL,灵感来源于 SwiftUI。
VaporDSL 提供了一个声明式的 API,允许您使用简单且结构化的语法构建后端服务器。 您可以在编写代码时理解服务器的结构。
重要提示: 有一个类似的名称叫做
RoutesBuilder
,它是 Vapor 框架提供的一个协议,它与RouteBuilder
不同,RouteBuilder
是 VaporDSL 的 result builder。 如果找到一个更好的名字,能够更好地代表 RouteBuilder 以防止误解,这个名字将来可能会被更改。
dependencies: [
// ...
.package(name: "VaporDSL", url: "https://github.com/danny1113/vapor-dsl.git", from: "1.0.0")
]
您可以通过在 Application
内容闭包中编写代码来创建整个 Web 应用程序。 您还可以在 then()
函数中初始化应用程序后执行其他设置,例如 Leaf、Fluent 和 Middlewares。
try Application {
// Group, Route, Controller...
}
.then { app in
print(app.routes.all)
// other additional setup...
}
.run()
或者,如果您正在使用 Vapor 提供的模板,由于 Group
符合 Vapor 提供的 RouteCollection
协议,您可以直接注册它。
func routes(_ app: Application) throws {
let collection = Group {
// Group, Route, Controller...
}
try app.register(collection: collection)
}
Group
是一个符合 RouteCollection
协议的结构体,它将分组并添加其所有子路由。 您可以通过在一个组内创建另一个组来创建更复杂的结构。
注意: 初始化没有
_ path
参数的Group
将对服务器结构没有影响。
// root path
Group {
// api
Group("api") {
// Route, Controller...
}
}
Route 代表服务器上的一个端点,它使用 Vapor 框架提供的 use(method:path:body:closure:)
来创建新路由。
注意: 初始化没有
_ path
参数的Route
将在其父级的根路径上创建一个路由。
Group("api") {
// default HTTPMethod: .GET
// GET /api/
Route(use: index)
// GET /api/todos
Route("todos") { req in
return req.view.render("todos")
}
// POST /api/todos
Route("todos", on: .POST, use: todo)
}
您还可以将其路由分组到自己的控制器中,只需简单地符合 RouteBuildable
协议即可。
struct LoginController: RouteBuildable {
var body: some RouteBuildable {
Group {
Route("login", on: .GET, use: login)
// Group, Route, Controller...
}
}
func login(req: Request) async throws -> View {
return try await req.view.render("login")
}
}
现在您已经学会了如何使用 Group
和 Route
,您可以使用结构化语法来构建您的服务器
try Application {
// GET /
Route { req in
return "Hello, world!"
}
Group("api") {
// GET /api/status
Route("status", on: .GET) { req in
return "ok"
}
}
LoginController()
}
.run()
MiddlewareGroup 将其所有路由分组到一个中间件中,您也可以将多个中间件链接在一起。
MiddlewareGroup(
UserAuthenticator(),
UserModel.guardMiddleware()
) {
Route("hello") { req in
return req.view.render("hello")
}
}