跳转至

第二章:你好,Vapor

使用一项新技术开始一个项目可能是令人生畏的。Vapor让你轻松入门。它提供了一个方便的命令行工具来为你创建一个启动项目。

在本章中,你将从安装Vapor工具箱开始,然后用它来建立和运行你的第一个项目。最后,你将学习路由、接受数据和返回JSON

Vapor工具箱

Vapor工具箱是一个命令行界面(CLI)工具,你在开发Vapor应用程序时使用。它可以帮助你从一个模板中创建一个新的Vapor项目,并可以根据需要添加依赖性。

在你安装工具箱之前,你需要确保你的系统已经安装了Swift。在macOS上,只需从Mac App Store上安装Xcode。在Linux上,从https://www.swift.org,如下面描述的那样安装。

Vapor 4需要Swift 5.2,无论是在Xcode还是在命令行。Xcode 11.411.5都提供Swift 5.2

macOS上安装

Vapor使用Homebrew来安装工具箱。

如果你没有安装Homebrew,请访问https://brew.sh,运行安装命令。

Terminal中,运行以下命令:

brew install vapor

Note

Vapor现在是Homebrew核心的一部分。如果你使用VaporHomebrew tap安装了旧版本的工具箱,你可以通过以下方式更新到最新版本:

brew uninstall vapor && brew untap vapor/tap && brew install vapor

这将从Homebrew的水龙头列表中删除Vapor,并安装Homebrew核心的最新版本的工具箱。

Linux上安装

本书主要侧重于使用XcodemacOS来开发你的应用程序。然而,你用Vapor构建的一切都可以在Swift支持的Linux版本上运行。Vapor工具箱的工作方式完全相同,但例外的是你不能在Linux上使用Xcode

安装Swift

要在Linux上安装Swift,请访问https://swift.org/download/并下载适合你的操作系统的工具链。按照安装步骤将工具链安装到你的机器上。完成后,在shell提示下输入以下内容:

swift --version

你应该得到返回的正确版本的Swift

img

安装Vapor

在你的控制台,运行以下命令:

# 1
git clone https://github.com/vapor/toolbox.git
# 2
cd toolbox
# 3
git checkout 18.0.0
# 4
swift build -c release --disable-sandbox
# 5
mv .build/release/vapor /usr/local/bin

下面是这个的作用:

  1. GitHub上克隆工具箱。
  2. 导航到你克隆的工具箱目录。
  3. 查看18.0.0版本。你可以在GitHub上的发布页面找到工具箱的最新版本,网址是https://github.com/vapor/toolbox/releases
  4. 以发布模式构建工具箱。--disable-sandbox允许工具箱执行其他进程。
  5. 把工具箱移到你的本地路径,这样你就可以从任何地方调用它。

本书在提到Linux时一直使用Ubuntu 20.04,但其他支持的Linux版本应该以完全相同的方式工作。

建立你的第一个应用程序

建立一个Vapor项目一开始可能会显得很复杂,因为有许多必要的文件和目录。为了帮助解决这个问题,工具箱可以根据模板创建一个新的项目。工具箱可以为一个简单的API、网站和认证生成模板。你甚至可以创建你自己的模板。

首先,在你的主目录或合理的地方创建一个新的目录来处理你的Vapor项目。例如,在终端输入以下命令:

mkdir ~/vapor
cd ~/vapor

这将在你的主文件夹中创建一个名为vapor的新目录,并将你引向那里。接下来,用以下方式创建你的项目:

vapor new HelloVapor

然后工具箱会询问你是否愿意使用Fluent和其他软件包。现在,请输入n,然后再输入Enter,就可以使用它们了。你以后会了解到Fluent和其他软件包。然后,工具箱将为你生成你的项目。

你应该看到以下内容:

img

要构建和启动你的应用程序,请运行:

# 1
cd HelloVapor
# 2
swift run

下面是这个的作用:

  1. cd是"改变目录"命令,带你进入项目目录。
  2. 构建并运行应用程序。第一次可能需要一些时间,因为它必须获取所有的依赖项。

img

该模板有一个预定义的路线,所以打开你的浏览器,访问http://localhost:8080/hello,就可以看到回应了!

img

Swift Package Manager

Vapor工具箱使用Swift Package ManagerSwiftPM--一个类似于iOSCocoaPods的依赖性管理系统--来配置和构建Vapor应用程序。打开你的项目目录,看一下结构。在macOSTerminal中,输入:

open .

img

注意在你的模板中没有Xcode项目,尽管你已经建立并运行了该应用程序。这是故意的。事实上,项目文件被明确地排除在使用.gitignore文件的源代码控制之外。当使用SwiftPM时,Xcode在一个名为.swiftpm的隐藏目录中创建一个工作区。

一个SwiftPM项目被定义在Package.swift清单文件中。它声明了目标、依赖性以及它们如何连接在一起。项目的布局也与传统的Xcode项目不同。有一个Tests目录用于测试。有一个Sources目录用于存放源文件。在您的清单中定义的每个模块在Sources中都有自己的目录。您的示例应用程序有一个App模块和一个Run模块,因此Sources包含一个App目录和一个Run目录。

Run目录下,有一个文件:main.swift。这是所有Swift应用程序所需的入口点。

Note

iOS上,这通常是用AppDelegate上的@UIApplicationMain属性合成的。

该模板包含了你设置应用程序所需的一切,你不应该需要改变main.swiftRun模块。你的代码住在App或你定义的任何其他模块中。

创建你自己的路由

Note

本节和本书的大部分内容一样,使用Xcode。如果你在Linux上开发,请使用你喜欢的编辑器,然后使用swift run来构建和运行你的应用程序。

现在你已经制作了你的第一个应用程序,是时候看看用Vapor添加新的路线有多容易。如果Vapor应用程序仍在运行,在终端按Control-C停止它。下一步进入:

open Package.swift

这将在Xcode中打开该项目作为SwiftPM工作区。Xcode将需要几分钟时间来下载依赖项。当它完成后,在Sources/App中打开routes.swift。你会看到你上面访问的路由。

要创建另一个路由,请在app.get("hello")闭包后添加以下内容:

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

下面是这个的作用:

  • 添加一个新的路由来处理一个GET请求。app.get的每个参数是URL中的一个路径组件。当用户输入http://localhost:8080/hello/vapor作为URL时,该路由被调用。
  • 当这个路由被调用时,提供一个闭包来运行。该闭包接收一个Request对象;你将在后面了解更多关于这些对象的信息。
  • 返回一个字符串作为这个路由的结果。

Xcode工具栏中,选择HelloVapor方案并选择My Mac作为设备。

img

建立和运行。在你的浏览器中,访问http://localhost:8080/hello/vapor

img

如果你想向任何访问你的应用程序的人打招呼,怎么办?添加世界上的每一个名字将是相当不切实际的! 一定有一个更好的方法。有的,Vapor让它变得简单。

添加一个新的路线,向任何访问的人问好。例如,如果你的名字是Tim,你将使用URLhttp://localhost:8080/hello/Tim访问应用程序,它说"你好,Tim!"。

在你刚才输入的代码后添加以下内容:

// 1
app.get("hello", ":name") { req -> String in
  // 2
  guard let name = req.parameters.get("name") else {
    throw Abort(.internalServerError)
  }
  // 3
  return "Hello, \(name)!"
}

以下是分解步骤的过程:

  1. 使用:name来指定一个动态参数。
  2. 提取用户的名字,在Request对象中传递。如果Vapor找不到名为name的参数,则抛出一个错误。
  3. 使用这个名字来返回你的问候语。

建立并运行。在你的浏览器中,访问http://localhost:8080/hello/Tim。尝试用一些其他的值替换Tim

img

接受数据

大多数网络应用必须接受数据。一个常见的例子是用户登录。要做到这一点,客户端会发送一个带有JSON主体的POST请求,应用程序必须对其进行解码和处理。要了解更多关于POST请求及其工作原理,请参见第3章,"HTTP基础知识"。

由于VaporSwiftCodable协议紧密结合,它使数据解码变得很容易。你给Vapor一个符合你预期数据的Codable结构,剩下的就由Vapor来完成。创建一个POST请求,看看它是如何工作的。

本书使用RESTed应用程序,可从Mac App Store免费下载。如果你愿意,你可以使用另一个REST客户端来测试你的API

设置请求如下:

  • URL: http://localhost:8080/info
  • Method: POST
  • 添加一个名为name的单一参数。使用你的名字作为值。
  • 选择JSON-encoded作为请求类型。这将确保数据以JSON格式发送,并且Content-Type头被设置为application/json。如果你使用一个不同的客户端,你可能需要手动设置。

你的请求应该类似于以下内容:

img

回到Xcode,打开routes.swift,在文件末尾添加以下内容,创建一个名为InfoDatastruct来表示这个请求:

struct InfoData: Content {
 let name: String
}

这个struct符合Content,是VaporCodable的包装。Vapor使用Content来提取请求数据,无论它是默认的JSON编码还是形式的URL编码。InfoData包含单一参数name

接下来,在app.get("hello", "vapor")闭包后添加一个新的路由:

// 1
app.post("info") { req -> String in
  let data = try req.content.decode(InfoData.self)
  return "Hello \(data.name)!"
}

下面是这个的作用:

  1. 添加一个新的路由处理程序来处理URLhttp://localhost:8080/infoPOST请求。这个路由处理程序返回一个String
  2. 使用InfoData对请求的主体进行解码。
  3. 通过从data变量中提取名称来返回字符串。

建立并运行应用程序。从RESTed发送请求,你会看到响应回来:

img

这看起来像是从JSON中提取一个参数的大量模板。然而,Codable可以扩展,并允许你在一行中解码复杂的、嵌套的、有多种类型的JSON对象。

返回JSON

Vapor还可以让你在路由处理程序中轻松返回JSON。当你的应用程序提供一个API服务时,这是一个常见的需求。例如,一个处理来自iOS应用的请求的Vapor应用需要发送JSON响应。Vapor再次使用Content将响应编码为JSON

打开routes.swift,在文件末尾添加以下结构,称为InfoResponse,以返回传入的请求:

struct InfoResponse: Content {
  let request: InfoData
}

这个struct符合Content的要求,并包含一个请求的属性。

接下来,将app.post("info")替换为以下内容:

// 1
app.post("info") { req -> InfoResponse in
  let data = try req.content.decode(InfoData.self)
  // 2
  return InfoResponse(request: data)
}

以下是变化的内容:

  1. 路线处理程序现在返回新的InfoResponse类型。
  2. 使用解码后的请求数据构建一个新的InfoResponse类型。

构建并运行该应用程序。从RESTed发送同样的请求。你会看到一个包含原始请求数据的JSON响应:

img

Vapor的故障排除

在本书的整个过程中,以及在今后的任何Vapor应用程序中,你可能会遇到项目中的错误。可以采取一些步骤来解决任何问题。

更新你的依赖性

你可能遇到的另一种情况是在Vapor或你使用的另一个依赖中遇到了错误。确保你是在任何依赖的最新软件包版本上,看看更新是否修复了这个问题。在Xcode中,选择File ▸ Swift Packages ▸ Update to Latest Package Versions。如果你在终端运行应用程序,或在Linux上,输入:

swift package update

这个SwiftPMSwiftPM命令会拉下你的依赖关系的任何更新,并在Package.swift中使用你支持的最新版本。请注意,当软件包处于测试版或候选版阶段时,更新之间可能会有突破性变化。

清理和重建

最后,如果你仍然有问题,你可以使用相当于"关闭并重新打开"的软件。在Xcode中,使用Command-Option-Shift-K来清理构建文件夹。

你可能还需要为Xcode项目以及工作区本身清除你的衍生数据。"核"选项涉及:

  • 删除.build目录以从命令行中删除任何构建工件。
  • 删除.swiftpm目录以删除Xcode工作空间和任何错误的配置。
  • 删除Package.resolved以确保你在下次构建时获得最新的依赖性。
  • 删除DerivedData以清除额外的Xcode构建工件。

Vapor Discord

上述步骤通常可以解决您可能遇到的大多数不是由您的代码引起的问题。 如果一切都失败了,请前往VaporDiscord服务器。 在那里你会发现成千上万的开发者在讨论Vapor,它的变化并帮助人们解决问题。 单击Vapor网站上的Join Chat按钮:https://vapor.codes

接下来去哪?

本章概述了如何开始使用Vapor以及如何创建基本路线。 本书的前两部分向您展示了如何构建一个复杂的应用程序,包括API、网站和两部分中的身份验证。 随着你逐步学习它们,你将学习如何使用核心Vapor概念,例如futuresFluentLeaf。 到第 2 部分结束时,您将拥有在Vapor中构建任何服务器端Swift应用程序的坚实基础。