基于Swift的Web框架Vapor2.0文档(翻译)HTTP-Body

转载请附原文链接:http://blog.fandong.me/2017/08/20/iOS-SwiftVaporWeb23/

前言

之前一直有做Java后台开发的兴趣,可是想到要看好多的Java教程,作为一个iOS开发者,我放弃了,
后来从朋友韩云智VL那里知道了这个框架,竟是用Swift写的,不得不说,它燃起了我的兴趣。
Vapor是一个基于Swift开发的服务端框架,可以工作于iOS,Mac OS,Ubuntu。
为了配合Swift部署到服务器,我把ECS的服务器系统改为Ubuntu16.04。

Vapor 2.0 - 文档目录
以下文字翻译自Vapor Docs/HTTP/Body

请求体

HTTP.Body表示的是HTTP.Message的有效载荷,并用于传递底层数据,在这次练习中的一些例子是JSON,HTML文本或者二进制图像,我们来看一下具体实现

public enum Body {
    case data(Bytes)
    case chunked((ChunkStream) throws -> Void)
}

数据案例

Data Case是一个目前最常见的Body中的HTTP.Message.它只是一个字节数组,与这些字节数组关联的序列化协议或类型通常由Content-Type请求头定义,我们来看些例子

Application/JSON

如果我们的Content-Type请求头包含application/json,那么底层二级制数据表示序列化的JSON

if let contentType = req.headers["Content-Type"], contentType.contains("application/json"), let bytes = req.body.bytes {
  let json = try JSON(bytes: bytes)
  print("Got JSON: \(json)")
}

Image/PNG

如果我们的Content-Type包含image/png,则底层二进制数据表示编码的png.

if let contentType = req.headers["Content-Type"], contentType.contains("image/png"), let bytes = req.body.bytes {
  try database.save(image: bytes)
}

分块案例

分块案例只适用于Vapor的外发的HTTP.Message,传统意义上,响应者的角色是在传递之前收集整个分块编码,我们可以使用它来异步发送一个正文.

let body: Body = Body.chunked(sender)
return Response(status: .ok, body: body)

我们也可以手动实现,也可以使用Vapor的内置便利的初始化器来进行对请求体进行分块.

return Response(status: .ok) { chunker in
  for name in ["joe", "pam", "cheryl"] {
      sleep(1)
      try chunker.send(name)
  }

  try chunker.close()
}

确保在分块离开范围之前调用close()

BodyRepressentable

除了具体的Body类型,就像在Vapor中常见,我们也广泛的支持BodyRepresentable.这意味着我们通常转换的类型的对象可以互换使用,举个栗子

return Response(body: "Hello, World!")

在上面的例子中,字符串被转换成二进制,并且添加到了请求体中

作为练习,最好使用Hello,World!Vapor会自动设置Content-Type为合适的值

我们来看看它是如何实现的:

public protocol BodyRepresentable {
    func makeBody() -> Body
}

自定义

我们也可以在适用的情况下遵照我们自己的类型,假设我们有一个自定义的数据类型,.vpr让我们符合我们的VPR文件类型

extension VPRFile: HTTP.BodyRepresentable {
  func makeBody() -> Body {
    // collect bytes
    return .data(bytes)
  }
}

你可能已经注意到,协议抛出,但是我们没有实现,这在Swift中完全有效,如果你曾经手动调用过这个方法,那你将无法抛出.

现在我们可以直接在我们的Responses中包含我们的VPR文件.

drop.get("files", ":file-name") { request in
  let filename = try request.parameters.extract("file-name") as String
  let file = VPRFileManager.fetch(filename)
  return Response(status: .ok, headers: ["Content-Type": "file/vpr"], body: file)
}

作为练习,如果我们经常重复这些过程,我们可能会让VPRFile直接遵循ResponseRepresentable

extension VPRFile: HTTP.ResponseRepresentable {
  func makeResponse() -> Response {
    return Response(
      status: .ok,
      headers: ["Content-Type": "file/vpr"],
      body: file
    )
  }
}

这是我们上面的例子

drop.get("files", ":file-name") { request in
  let filename = try request.parameters.extract("file-name") as String
  return VPRFileManager.fetch(filename)
}

我们也可以使用类型安全的路由使其更简洁:

drop.get("files", String.self) { request, filename in
  return VPRFileManager.fetch(filename)
}

你可能感兴趣的:(基于Swift的Web框架Vapor2.0文档(翻译)HTTP-Body)