Swift Web 开发之 Vapor - 路由(二)

上篇文章带你们基本了解了一下开始一个 Vapor 项目的流程,本篇紧接着来讲说在全部 Web 框架中都最关键的 “路由”,由于 “路由” 模块在 Web 项目中担任很重要的角色,因此不少语言的 Web 框架都把 “路由” 抽离到框架层,从而减小开发者的工做量,一个设计得易用强大的 “路由” 系统也会给相应给框架增添很多色彩。html

Web 开发中的路由这个概念简单来讲就是 URL 路径到具体处理函数之间的映射,只有设定好了路由,访问者才能在浏览器根据相关 URL 规则进行页面跳转和访问,Vapor 对路由作了不少实用性设计,包括路由的构建、路由组、类型安全的路由参数、路由集合等等,但愿看完本篇文章你能用 Vapor 写出一些简单的路由,咱们先来看看 Vapor 最简单的路由注册。git

Droplet

注册路由以前咱们须要知道 Droplet 这个类,每一个程序都应该有一个它的实例,控制着整个程序的生命周期,以后咱们会经过 droplet 来注册路由,添加 provider,添加中间件 (middleware) 等等。 droplet 的初始化很简单,一个空程序看起来就像这样:github

import Vapor
let drop = Droplet()
// your magic here
drop.run()复制代码

注册路由

注册一个最基本的路由经过对全局 Droplet 对象调用一个方法,指定路径和一个闭包来接收操做处理。json

drop.get("welcome") { request in
    return "Hello"
}复制代码

咱们经过调用 get() 方法来注册了一个路径为 /welcome 的路由,并返回了 "Hello" 这个字符串到浏览器,固然咱们除了 get 还能够其余的标准 HTTP 方法,好比 postputpatchdeleteoptionsswift

另外咱们还可使用 add() 方法来注册路由,以接收第一个参数 Method 做为 HTTP 方法来动态注册路由,Method 是一个枚举,包含了上述所列的 HTTP 标准方法,代码看起来是这样:浏览器

drop.add(.trace, "welcome") { request in
    return "Hello"
}复制代码

可能你会想明明上面已经提供了对应的方法来注册路由,为何还要多一个 add() 方法来注册路由?由于这个方法能够动态注册,而且支持一些其余不常见的方法(好比 trace)。安全

另外有一种关于多级路径的写法,直接使用参数分割,而不是在一个 String 参数中用 / 分开,官方推荐是这种写法,由于能够更容易写出类型安全的路由参数。闭包

drop.get("foo", "bar", "baz") { request in
    return "You requested /foo/bar/baz"
}复制代码

若是想在 URL 路由中使用通配符怎么办?app

app.get("anything", "*") { request in
    return "Matches anything after /anything"
}复制代码

像这个例子由于用了 * 尾随参数,能够匹配到以下全部路径:框架

  • /anything
  • /anything/foo
  • /anything/foo/bar
  • /anything/foo/bar/baz

Request

每一个路由的闭包都会有一个 Request 参数,用来得到每个访问请求的相关内容,好比 URL 参数、HTTP Header、HTTP Body 等等,并且 Vapor 都已经为你封装好了很方便的接口来获取这些内容,甚至直接解析 JSON。

详细使用能够参考官方文档 Request 一节。

路由参数

Vapor 提倡使用类型安全的路由参数来接收数据,咱们能够在路由方法中使用 Swift 类型来指定参数类型,Vapor 会在内部解析并将参数返回给闭包以供使用,很是方便。

drop.get("users", Int.self) { request, userId in
    return "You requested User #\(userId)"
}复制代码

Swift 中到处有协议,路由参数也是如此,咱们所见例子中的 Int 其实就是 Vapor 给实现了 StringInitializable 协议,固然 String 也已经默认实现。

public protocol StringInitializable {
    init?(from string: String) throws
}复制代码

Response

每一个路由的闭包中能够返回三种类型的内容,ResponseResponseRepresentablethrow,你能够你能够返回本身所需的 HTTP 状态码、URL 重定向、JSON等,基本涵盖平常所需的请求返回。

Response

Response 是 Vapor 中 HTTP 模块中定义的基于 Message 的类,有不少构造方法方便咱们自定义 response 返回:

// 重定向
Response(redirect: "http://vapor.codes")

// JSON
Response(status: .ok, json: JSON(["hello":"world"]))

// String
Response(body: "hello")复制代码
ResponseRepresentable

ResponseRepresentable 是一个协议,任何遵循这个协议的对象都可在路由中返回,就像以前例子中咱们直接返回了字符串,就是由于 Vapor 默认给 String 实现了 ResponseRepresentable 协议,让咱们能够方便的在闭包中直接返回字符串,相似的还有 JSONModel 对象。

throw

另一大特性就是能够直接在路由中抛出异常,咱们能够 throw 任何听从 Swift.Error 协议的对象,固然 Vapor 已经为咱们封装好了几个经常使用的 Error 来方便咱们抛出异常。

drop.get("404") { request in
    throw Abort.notFound
}复制代码

当咱们请求这个地址的时候通常会看到一个 Vapor 默认提供的错误页面,还挺漂亮的,若是不想用 Vapor 提供的默认错误页面,咱们能够从 drop.middleware 中移除 AbortMiddleware 并添加本身的实现便可。

vapor404

Abort 枚举在 Vapor 中定义以下:

public enum Abort: Swift.Error {
    case badRequest
    case notFound
    case serverError
    case custom(status: Status, message: String)
}复制代码

Status 枚举了几十个咱们可能用到的 HTTP 状态码,如 200(.ok)、 301(.movedPermanently)、403(.forbidden) ...

路由组

Vapor 提供了路由组的概念,一般用来集中组织一组相同前缀,添加中间件,限制主机名,或者集中管理的路由,路由组有两个类型:GroupGrouped

Group 经过一个闭包来收纳旗下全部的路由,让它们有统一的路径前缀,示例以下:

drop.group("v1") { v1 in
    v1.get("users") { request in
        // get the users
    }
}复制代码

Grouped 原理相似,只是形式上有所变化,经过 drop.grouped() 方法返回一个 RouteGroup 对象来收纳路由。

let v1 = drop.grouped("v1")
v1.get("users") { request in
    // get the users
}复制代码

文章到此关于 Vapor 路由基本的内容也差很少都介绍完毕了,固然这里讲的可能并不全面,示例代码基原本自于官方文档(感谢 🙏),下一篇准备说说 Vapor 的模版引擎 Leaf。

以前开的坑在写一个博客程序 NSPress,若是你们有兴趣欢迎讨论。

相关文章
相关标签/搜索