Ginny 是一个 Swift Package 插件,它为 Vapor 应用启用基于文件的路由。它的工作原理是在构建时生成代码,这些代码像在任何普通的 Vapor 应用中一样注册路由。
Ginny 移除了 Vapor 应用中与路由相关的样板代码,同时支持其大部分功能。(有关不支持功能的列表,请参见下文。)
使用 Ginny 就像进行一行代码的更改一样简单
let app = try Application(.detect())
defer { app.shutdown() }
+ app.registerRoutes()
try app.run()
从现在开始,只要插件正在运行,路由将根据您在 Vapor 应用的目标中组织文件的方式以及文件中的内容生成。
以下文件夹结构
pages/
├── api/
│ ├── hello.swift
│ ├── world
│ │ ├── world.index.swift
│ │ ├── foo.swift
产生以下路由
/api/hello
/api/world
/api/world/foo
Ginny
会在您的 /pages
目录中查找包含符合 RequestHandler
或 AsyncRequestHandler
的 .swift
文件,并为您生成其余的路由注册代码。
例如,以下文件 /pages/api/hello.swift
import Foundation
import Ginny
import Vapor
struct Hello: RequestHandler {
var method: HTTPMethod {
.GET
}
func handle(req: Request) throws -> String {
"Hello, world!"
}
}
每次构建项目时,Ginny 都会在 /pages/api/hello.swift
中找到 RequestHandler
,并在后台生成 Vapor 样板代码以注册您的路由。您始终可以通过检查目标构建日志中的 Routes.generated.swift
来查看 Ginny 生成的确切代码。
从这里,您可以像往常一样运行服务器,并向相应的端点发出请求
curl -X GET https://:8080/api/hello
Package.swift
中添加 Ginny 作为依赖项.package(url: "https://github.com/gonzalonunez/ginny.git", from: "0.1.1"),
Ginny
库添加为依赖项,并将 GinnyPlugin
添加为插件。 请参阅示例应用以获取更多信息。.executableTarget(
name: "MyApp",
dependencies: [
.product(name: "Ginny", package: "ginny"),
.product(name: "Vapor", package: "vapor"),
],
plugins: [
.plugin(name: "GinnyPlugin", package: "ginny"),
]),
现在,只要您构建项目,并且您的任何 API 路由已更改,Ginny 就会运行。
关于 Ginny 如何为您生成代码,有一些需要注意的地方
通常,在其他系统中,名为 index
的文件用于指代目录的根目录。不幸的是,这在 Swift 中不起作用,因为同一个模块中不能有两个同名的文件。 Ginny 通过删除包含 .index
的任何路径组件来解决这个问题,无论是文件还是文件夹。 这允许您用任何其他需要消除歧义的内容作为 index
文件的前缀。 因此,api/hello/hello.index.swift
被路由到 api/hello
,而 api/hello/world/world.index.swift
被路由到 api/hello/world/
。 请参阅示例应用以获取更多信息。
Ginny 足够智能,可以支持同一个文件中的两个 RequestHandler
,它将为您注册它们。 因此,您可以在同一个文件中声明具有不同 HTTP 方法的多个处理程序,并获得您期望的行为:例如,GET api/hello
和 POST api/hello
。
Ginny 根据文件系统按字母顺序注册路由。 您始终可以在构建日志中检查 Routes.generated.swift
以查看 Ginny 生成的代码。 如果您想要不同的行为,请提交一个 GitHub issue。
目前,Ginny 支持 Vapor 的大多数路由功能。 如果有任何需求,可以添加对缺失功能的支持,请提交一个 GitHub issue 以进行讨论!
路由参数:Vapor 的路由参数使用 []
语法支持。 例如,名为 api/user/[id].swift
的文件最终会在 Vapor 中注册为 api/user/:id
Catchall 参数:Vapor 的 catchall 参数使用 ...
语法支持。 例如,名为 api/user/[...slug].swift
的文件最终会在 Vapor 中注册为 api/user/***
,并允许您稍后检索 catchall。 slug
部分无关紧要,您可以随意命名(如果您想在同一个模块中有多个支持 catchall 参数的文件,您将必须这样做,因为同一个 Swift 模块中不能有两个同名的文件)
路由中间件:通过在您的 RequestHandler
中提供一个 middlewares
数组,该数组将与应用程序当前的中间件一起进行分组,从而支持 Vapor 的路由中间件
Ginny 的灵感来自 Vercel 进行路由的方式。 我是 Vercel 和 Next.js 的忠实拥趸,我强烈建议您去了解一下。
Ginny Strazisar 在 1975 年开发了 第一个真正的 IP 路由器。