vapor学习教程-Route Parameters

2017-04-08  本文已影响0人  晓蜻蜓

Routing Parameters

传统的Web框架通过使用路由参数名称和类型的字符串为路由留出错误空间。vapor利用Swift的关闭来提供更安全和更直观的访问路线参数的方法。

Type Safe


要创建一个类型安全的路由,只需用“类型”替换路径中的一部分。

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

这将创建一个匹配的路径users/:id,其中:id是一个Int类型。这是使用手动路由参数。

drop.get("users", ":id") { request in
  guard let userId = request.parameters["id"]?.int else {
    throw Abort.badRequest
  }

  return "You requested User #\(userId)"
}

在这里,可以看到类型安全路由保存~3行代码,并且还可以防止运行时错误,如拼写错误:id

String Initializable


任何符合的类型StringInitializable都可以用作类型安全的路由参数。默认情况下,以下类型符合:

String是最通用的,总是匹配。Int只有当提供的字符串可以变成一个整数时才匹配。Model仅当用作标识符的字符串可用于在数据库中查找模型时才匹配。
以前的user例子可以进一步简化:

drop.get("users", User.self) { request, user in
  return "You requested \(user.name)"
}

提供的标识符将自动用于查找用户。例如,如果/users/5被请求,User模型将被要求具有标识符的用户5。如果找到,则请求成功并且调用关闭。如果没有,则抛出未找到的错误。
如果模型不符合StringInitializable这将会怎么样?

drop.get("users", Int.self) { request, userId in
  guard let user = try User.find(userId) else {
    throw Abort.notFound
  }

    return "You requested User #\(userId)"
}

总而言之,类型安全路由可以从每个路由节省大约6行代码。

Protocol


创建符合StringInitializable的类型是简单的:

public protocol StringInitializable {
    init?(from string: String) throws
}

Here is what Model's conformance looks like for those who are curious.

extension Model {
    public init?(from string: String) throws {
        if let model = try Self.find(string) {
            self = model
        } else {
            return nil
        }
    }
}

init方法可以同时throw和返回nil。这允许throw自己的错误。或者,如果想要默认的错误和行为,只需返回nil

Limits


类型安全路由目前仅限于三个路径部分。通常通过添加路由组来解决这个问题。

drop.group("v1", "users") { users in
  users.get(User.self, "posts", Post.self) { request, user, post in
    return "Requested \(post.name) for \(user.name)"
  }
}

上述示例的结果路径是/v1/users/:userId/posts/:postId

Manual


如上所述,仍然可以自由地进行传统路由。这对于特别复杂的情况可能是有用的。

drop.get("v1", "users", ":userId", "posts", ":postId", "comments", ":commentId") { request in
  let userId = try request.parameters.extract("userId") as Int
  let postId = try request.parameters.extract("postId") as Int
  let commentId = try request.parameters.extract("commentId") as Int

  return "You requested comment #\(commentId) for post #\(postId) for user #\(userId)"
}

属性request.parameters用于提取在URI 路径中编码的参数(例如,/v1/users/1具有:userId等于的参数"1")。在参数作为查询的一部分被传递的情况下(例如/v1/search-user?userId=1),就可以使用request.data获取参数值(例如let userId = request.data["userId"]?.string)。

请求参数可以作为字典访问,也可以使用 extract抛出而不是返回可选的语法。

Groups

手动请求参数也适于组合

let userGroup = drop.grouped("users", ":userId")
userGroup.get("messages") { req in
    let user = try req.parameters.extract("userId") as User
}

继续学习vapor学习教程-目录

上一篇 下一篇

猜你喜欢

热点阅读