4

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

 2 years ago
source link: https://www.isaced.com/post-283.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

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

1240

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

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

Droplet

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

import Vapor
let drop = Droplet()
// your magic here
drop.run()

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

drop.get("welcome") { request in
    return "Hello"
}

我们通过调用 get() 方法来注册了一个路径为 /welcome 的路由,并返回了 “Hello” 这个字符串到浏览器,当然我们除了 get 还可以其他的标准 HTTP 方法,比如 postputpatchdeleteoptions

另外我们还可以使用 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.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。

之前开的坑在用 Vapor 写一个博客程序 NSPress,如果大家有兴趣欢迎讨论。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK