跳转至

开发

这篇介绍使用Swfit语言构建一个简单的Web服务,它在数据库中存放待办事项,客户端可以通过RESTful接口访问。

这里使用IBM KituraWeb开发框架,它与已有的Web框架如:Ruby的Sinatra、Python的Flask以及NodeJS的Express.js很类似。

Kitura包含一个HTTP服务器,可以用来侦听来自客户端的请求,并把这些请求路由给合适的处理程序处理。

要想处理客户请求,我们的项目在使用SwiftPM导入Kitura模块后,需要先创建一个Router, 用来接收客户请求并路由到指定的处理程序中。

import Kitura

let router = Router()

但是在我们可以处理客户请求之前,需要先启动一个HTTP服务器来侦听客户请求,这里我们启动了一个在TCP端口8000上侦听客户请求的HTTP服务器,并把它注册给上面我们创建的router

Kitura.addHTTPServer(onPort:8000, with: router)

Kitura.run()

注意 - Kitura运行时支持同时开启多个HTTP服务器,它们可以在不同的端口上侦听客户请求,当然为了安全的话,也可以创建HTTPS服务器来代替HTTP服务器。

当服务器接到一个客户请求后,Kitura会创建一个线程用来执行针对这个客户请求的处理程序。

请求处理程序可以用一个闭包来定义,它有三个类型分别为:RouterRequestRouterResponse() -> Void的参数。

  • RouterRequest包含客户端请求的相关信息,其中可能有包含用户身份认证的请求头信息或者包含其它相关数据。
  • RouterResponse包含服务端要返回给客户端的相关信息。
  • () -> Void是服务端用于处理指定客户请求的处理程序,它也是一个闭包,可以自定义名称。

下面就创建一个可以处理来自主机路径/hello的GET请求,并返回Hello, World给客户的路由:

router.get("/hello"){ request, response, callNextHandler in 
    response.status(.OK).send("Hello, World!")
    callNextHandler()
}

注意 - 路径/hello中也可以指定正则表达式,用来匹配一系列指定的用户请求,其中以:开始的标识符可以做为参数传递给请求处理程序,例如:路径/user/:name可以匹配一个user/robert这样的用户请求,:name这个标识符就匹配了具体的robert,在请求处理程序中,可以通过request.parameters["name"]来获得:name匹配的具体值。

一个请求处理程序在处理完用户讲求时必须调用callNextHandler()或者response.end()来表示请求处理完成,否则客户端会一直等待服务端响应。

以上就是最简单的一个Web服务,全部代码如下:

import Kitura

let router = Router()

router.get("/hello"){ request, response, callNextHandler in 
    response.status(.OK).send("Hello, World!\n")
    callNextHandler()
}

Kitura.addHTTPServer(onPort:8000, with: router)

Kitura.run()

运行后,使用命令行工具curl来模拟客户请求测试服务是否正确:

$ curl localhost:8000/hello
Hello, World!

布署

开发完成的Web服务可以通过Docker来布署,也可以使用IBM Cloud Tools for Swift来布署到IBM Bluemix上。

因为服务器一般需要命令行操作,所以这里介绍使用服务行部署服务的过程,这里将使用IBM Bluemix云服务, 它可以试用30天,需要注册一个帐号并且需要开通CloudFoundry应用程序服务。

ibm-bluemix

ibm-bluemix-cloundFoundry

可以在相关界面下载CLI命令行工具用来布署应用。

ibm-bluemix-cli

下载并完成Bluemix-CLI的安装。

布署前需要创建几个文件,用来指定服务在部署的一些运行参数和信息。

创建manifest.yml文件

manifest.yml

applications:
 - name: todolist
   memory: 256M
   instances: 1
   random-route: true
   buildpack: https://github.com/IBM-Swift/Swift-buildpack.git

创建Procfile文件

Procfile

web: Server

项目代码中包含部署相关的代码

Package.swift文件中添加Swift-cfenv

Package.swift

// swift-tools-version:3.1

import PackageDescription

let package = Package(
    name: "todolist",
    dependencies: [
    .Package(url: "https://github.com/IBM-Swift/Kitura", majorVersion: 1, minor: 7),
    .Package(url: "https://github.com/IBM-Swift/Swift-cfenv", majorVersion: 4, minor: 0),
    ]
)
并在项目代码中包含下面代码:

import CloudFoundryEnv
do { 
    let appEnv = try CloudFoundryEnv.getAppEnv()
    let port: Int = appEnv.port
    Kitura.addHTTPServer(onPort: port, with: router)
} catch CloudFoundryEnvError.InvalidValue {
    print("Oops, something went wrong... Server did not start!")
}

参考资料

详情请参考IBM出口书籍及相关代码: