Vapor 教程
路由与请求处理
路由就是一张「网址 → 处理函数」的地图。它决定了「用户访问 /hello 时,哪段代码来回应」。这篇把 GET、POST、路径参数和 JSON 收发一次讲清。
一、路由到底是什么
把服务器想象成一家公司的前台:访客(浏览器/App)进门说「我要找张三」,前台根据名单把他引到对应办公室。这里的「名单」就是路由表——它把请求(通常是一个 URL + HTTP 方法)和处理这段代码(一个函数)对应起来。
在 Vapor 里,这份名单写在 routes.swift 中。一个最朴素的路由:
import Vapor
func routes(_ app: Application) throws {
app.get { req in
return "It works!"
}
}app.get 表示「响应 GET 请求」,没写路径就代表根路径 /。访问它,返回纯文本。
二、路径参数:让网址带变量
想让 /hello/小明 返回「Hello, 小明」?用命名占位符 :name 把路径里那段「捕获」下来:
app.get("hello", ":name") { req -> String in
guard let name = req.parameters.get("name", as: String.self) else {
return "\(HTTPStatus.notFound)"
}
return "Hello, \(name)"
}加上前面两个,你现在有了三组映射:
/→ 返回It works!/hello→ 返回Hello, world!/hello/小明→:name自动取出路径值,返回Hello, 小明
三、接收 POST 数据(JSON)
GET 用来「取」,POST 通常用来「交」。前端会发一段 JSON 过来,比如新建一个缩略语:
{ "short": "OMG", "long": "Oh My God" }Vapor 借助 Swift 的 Codable 协议,把 JSON 直接解码成结构体,几乎不用手写解析:
struct CreateAcronymData: Content {
let short: String
let long: String
}
app.post("api", "acronyms") { req -> String in
let data = try req.content.decode(CreateAcronymData.self)
return "收到:\(data.short) = \(data.long)"
}为什么省心:只要你的结构体遵循
Content(它内部已经包含 Codable),Vapor 就自动完成「JSON ↔ 结构体」的转换,不用像某些框架那样逐个字段手动取值。四、返回 JSON 而不是纯文本
写接口时,前端更想要 JSON。任何遵循 Encodable 的对象都可以直接作为响应返回:
struct Greeting: Content {
let message: String
}
app.get("greet") { req in
return Greeting(message: "Hello from Vapor")
}访问 /greet,你会得到 {"message":"Hello from Vapor"}。Vapor 根据返回类型自动选择 Content-Type,文本就返回纯文本,结构体就返回 JSON。
五、读取查询参数和请求头
除了路径里的值,URL 问号后面的查询参数也很常用:
app.get("search") { req -> String in
let q = req.query["q"] ?? "无"
return "你在搜:\(q)"
}访问 /search?q=vapor 得到「你在搜:vapor」。请求头则通过 req.headers 读取,比如取 req.headers["Authorization"] 来做认证(后面专篇讲)。
六、新手常踩的几个坑
- 路由顺序:把更具体的路由写在前面,避免被通配路由提前截胡。
- 参数类型:用
req.parameters.get("id", as: Int.self)明确类型,少了as:往往是返回 nil 的元凶。 - 异步返回:涉及数据库时处理函数返回的是
Future<T>而不是T,别直接当普通值用(下一篇控制器里会细说)。