接收客户端数据 封面
Vapor 大型教程

接收客户端数据

POST 请求里的 JSON 需要先解码成类型,再进入业务逻辑。这里用 Content 协议接收字段,并处理缺少字段或格式不对的请求。

Content 协议:从请求中提取数据

Content 协议是 Vapor 对 Codable 协议的封装,用来从请求中提取数据。添加遵守 Content 协议的结构体 InfoData,它只有一个 name 字符串成员,Content 协议支持请求数据向结构体对象的解码转换。在 routes 文件中添加下面代码,编译运行。

POST 请求

import Vapor

func routes(_ app: Application) throws {
    app.get { req in
        return "It works!"
    }

    app.get("hello") { req -> String in
        return "Hello, world!"
    }

    // Add Routes
    app.get("hello", ":name") { req -> String in
        guard let name = req.parameters.get("name", as: String.self) else {
            return "\(HTTPStatus.notFound)"
        }
        return "Hello, \(name)"
    }
    // ---
    app.post("info") { req -> String in
        let info = try req.content.decode(InfoData.self)
        return "Hello, \(info.name)"
    }
}
struct InfoData: Content {
    let name: String
}

用 curl 测试路由

我们使用 curl 这个工具来测试我们的路由是否正常工作,这个工具是类 Linux 系统都自带的命令行工具,不存在收费问题,可以免费使用,而且学习后端是必须掌握这个命令行工具的使用方法的。

  • -X 表示请求类型:GET / POST / PUT / DELETE,默认为 GET。
  • -H 请求发起时的 Headers 设置。
  • -d 请求发起时所携带的数据。

curl 测试命令:

curl http://localhost:8080/info \
-X POST \
-H "content-type:application/json" \
-d '{"name":"joker"}' 

输出:

Hello, joker

输入校验与错误响应

把 JSON 解码成结构体只解决了“格式能否读取”,并不代表数据可以直接写入数据库。生产接口还应检查必填字段是否为空、字符串长度是否合理,以及字段之间的业务约束。校验失败时返回 400 Bad Request,并在响应中给出稳定的错误字段,客户端才能准确提示用户。

guard !data.name.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else {
    throw Abort(.badRequest, reason: "name 不能为空")
}

同时建议限制请求体大小,并只在开发环境返回详细解码错误;生产环境记录服务端日志,向客户端返回不包含内部实现细节的提示。

Rested(已弃用)

之前使用一个 Mac 上名叫 rested 的应用,模拟 POST 请求(现在这个 App 开始收费,不能免费使用了,并且在中国区无法下载)。

本系列其他文章