因为不可抗力没上班,看着新swiftswiftUI发布,决定搞Perfect

这个框架可是听说很久了,匆忙看了两眼就没有下文。当时来说是最强 Server-site 框架(为什么要说当时?)

篇幅不长,仅做一个尝试和介绍,原因在最后。

安装

安装还是相当容易,官方编译器起一个可执行类型项目

1
swift package init --type=executable

其次,在Package.swift中添加依赖

1
2
3
dependencies: [
.package(url: "https://github.com/PerfectlySoft/Perfect-HTTPServer.git", from: "3.0.0")
],

接着,编译即安装依赖(熟悉啊!)

1
swift build

最后,生成xcodeproj文件以xcode打开,接下来工作交还给xcode

1
swift package generate-xcodeproj

不得不说,你果XCode到从系统10.10开始那会到如今 9102 年了,体验还是这么糟糕。然而苹果家的两个语言,不用XCode体验更糟…

编写体验

初始化项目什么目录都没有,作为一个毫无后端经验的 API 拼装师,只能假把式创建controllersmodels目录,加上习惯加一个constant目录。

后来发现,我好像用不上

按照习惯创建了一个结构体用来存放配置内容

1
2
3
4
struct GlobalConfig {
let baseRoute = "/api/v1"
let httpPort = 8081
}

接着,清空main.swift,根据swift的逻辑:只有库需要引用,业务文件同一项目下不需要import。所以引入perfect,并初始化

1
2
3
4
5
6
7
8
import PerfectHTTP
import PerfectHTTPServer
// 字典不是JSON,使用库中方法得以把字典转为JSON
import PerfectLib

let config = GlobalConfig()
let server = HTTPServer()
var routes = Routes(baseUri: config.baseRoute)

然后制定一个restful类型路由(原本写在Router.swift

1
2
3
4
5
6
7
let list: [[String: Any]] = [
["name": "index", "url": "/home", "method": HTTPMethod.get],
["name": "show", "url": "/home/{id}", "method": HTTPMethod.get],
["name": "create", "url": "/home", "method": HTTPMethod.post],
["name": "update", "url": "/home/{id}", "method": HTTPMethod.put],
["name": "delete", "url": "/home/{id}", "method": HTTPMethod.delete]
]

接着,通过swiftmap(不是很合适)随便载入一套路由(有时候真的恨swift的类型安全)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
RoutesConfig().list.map {
routes.add(method: $0["method"] as! HTTPMethod, uri: $0["url"] as! String, handler: { (request, response) in
let json: [String: Any] = ["code": 0, "message": "success"]
let variables = request.urlVariables
var newJson = json
if (!variables.isEmpty) {
for e in variables {
newJson[e.key] = variables[e.key]
}
}
let output = try! newJson // 因都是字面量,所以必有值(真nm安全,业务尽量不要这么搞)
.jsonEncodedString()
response
.setHeader(.contentType, value: "application/json")
.appendBody(string: output)
.completed()
})
}

路由载入服务并指定端口(直接执行会默认0.0.0.0:8081

1
2
server.addRoutes(routes)
server.serverPort = UInt16(config.httpPort)

最后(简单)执行

1
2
3
4
5
do {
try server.start()
} catch {
fatalError("\(error)")
}

原因

  • 文档虽是详细,但是周边很少,社区冷淡(都不知道有没有)。而且资料很少,很难查到关于这个框架的讨论或者内容。
  • Star 虽然证明不了什么,但是从昔日第一,到现在第二,距离第一也有很大差距。又语言关系,并不会有像某些库那样的宗教化。故必有某些原因。

所以,你好Vapor!这可能是目前swift server side最优解决方案。并且这也是标题从“零”开始的原因。

并且在文章提交之前,发现Vapor已经支持Swift 5.1,本体也更新频繁,大概知道为什么Perfect为什么会没落了。

不过,我觉得可以先尝试Vapor,再看看哪个使用手感更适合我。