SlideShare a Scribd company logo
 2016/09/10 H-LANE #hackt_h
HACKER TACKLE
Server Side? Swift
About Me
• 田中 孝明 (Takaaki Tanaka)
• クラスメソッド株式会社
• iOS アプリケーションエンジニア
• @kongmingtrap
• iOS Developer (Swift / Objective-C)
• GyazSquare / GitHub
Me and Fukuoka
ちょうど1年前まで住んでいました
Summary of Swift
Swift
Swift is a powerful and intuitive
programming language for macOS, iOS,
watchOS and tvOS. Writing Swift code is
interactive and fun, the syntax is concise
yet expressive, and Swift includes
modern features developers love. Swift
code is safe by design, yet also produces
software that runs lightning-fast.
History of Swift
• 0.x (2014/06)
• 1.0 (2014/09)
• 1.1 (2014/10)
• 1.2 (2015/02)
• 2.0 (2015/06)
• 2.1 (2015/10)
• 2.2 (2016/03)
• 3.0 (2016/09)
History of Swift
• 0.x (2014/06)
• 1.0 (2014/09)
• 1.1 (2014/10)
• 1.2 (2015/02)
• 2.0 (2015/06)
• 2.1 (2015/10)
• 2.2 (2016/03)
• 3.0 (2016/09)
黎明期
History of Swift
• 0.x (2014/06)
• 1.0 (2014/09)
• 1.1 (2014/10)
• 1.2 (2015/02)
• 2.0 (2015/06)
• 2.1 (2015/10)
• 2.2 (2016/03)
• 3.0 (2016/09)
成長期
History of Swift
• 0.x (2014/06)
• 1.0 (2014/09)
• 1.1 (2014/10)
• 1.2 (2015/02)
• 2.0 (2015/06)
• 2.1 (2015/10)
• 2.2 (2016/03)
• 3.0 (2016/09)
全盛期
[swift-evolution] Looking back on
Swift 3 and ahead to Swift 4
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160725/025676.html
ABI安定化など、Swift 3.0で実装予定だっ
た機能が見送られ、Swift 4.0まで持ち越
される。。。
Swift is Open Source
https://developer.apple.com/swift/blog/?id=34
Going Server-side with Swift Open Source
https://developer.apple.com/videos/play/
wwdc2016/415/
WWDC2016
Architecture
https://developer.apple.com/videos/play/
wwdc2016/415/
Architecture
https://developer.apple.com/videos/play/
wwdc2016/415/
Agenda
• Server Side Swift frameworks
• Environment construct
• Make
• Deploy
Server Side Swift frameworks
Server Side? Swift
https://github.com/PerfectlySoft/Perfect
Perfect
Perfect
• Swift における Rails の立ち位置を目指す
• 豊富なDB接続ライブラリ
• Mustacheテンプレート
• FastCGI + apache2 or Nginx
http://qutheory.io/
VAPOR
VAPOR
• Laraval like
• シンプルに記述できることを目指す
• ドキュメントが丁寧にまとめられている
https://github.com/vapor/vapor
https://developer.ibm.com/swift/kitura/
KITURA
KITURA
• IBM製
• IBMのクラウドプラットフォームBluemixがSwiftに対
応
• サンドボックスで試すことができる
• Swift関連の取り組みも熱心
https://github.com/IBM-Swift
http://www.zewo.io/
Zewo
Zewo
• 豊富なパッケージ数
• BaseComponentsをVaporと入れ替えることができ
る
https://github.com/Zewo
https://github.com/necolt/Swifton
Swifton
https://github.com/necolt/Swifton
Swifton
• Ruby on Rails like
https://github.com/noppoMan/Slimane
Slimane
https://github.com/noppoMan
Slimane
• expressにインスパイア
• マイクロフレームワーク+HTTPサーバー
• Yuki Takeiさん作成
Environment construct
今回のデモで採用
8000 star over.
Perfect Template
https://github.com/PerfectlySoft/PerfectTemplate.git
Build
Xcode 8.0 or later
OS X El Captan (10.11.6)
$ swift —version
Apple Swift version 3.0 (swiftlang-800.0.43.6 clang-800.0.38)
Target: x86_64-apple-macosx10.9
$ xcode-select --switch /Applications/Xcode.app/Contents/Developer
Build
$ brew install openssl
$ brew link openssl --force
Build
$ git clone https://github.com/PerfectlySoft/PerfectTemplate.git
$ cd PerfectTemplate
$ swift build
$ .build/debug/PerfectTemplate
Server Side? Swift
// Create HTTP server.
let server = HTTPServer()
// Register your own routes and handlers
var routes = Routes()
// Add the routes to the server.
server.addRoutes(routes)
// Set a listen port of 8181
server.serverPort = 8181
// Set a document root.
// This is optional. If you do not want to serve static content then do not set this.
// Setting the document root will automatically add a static file handler for the route /**
server.documentRoot = "./webroot"
// Gather command line options and further configure the server.
// Run the server with --help to see the list of supported arguments.
// Command line arguments will supplant any of the values set above.
configureServer(server)
do {
// Launch the HTTP server.
try server.start()
} catch PerfectError.networkError(let err, let msg) {
print("Network error thrown: (err) (msg)")
}
Server Start
// Create HTTP server.
let server = HTTPServer()
// Register your own routes and handlers
var routes = Routes()
// Add the routes to the server.
server.addRoutes(routes)
// Set a listen port of 8181
server.serverPort = 8181
// Set a document root.
// This is optional. If you do not want to serve static content then do not set this.
// Setting the document root will automatically add a static file handler for the route /**
server.documentRoot = "./webroot"
// Gather command line options and further configure the server.
// Run the server with --help to see the list of supported arguments.
// Command line arguments will supplant any of the values set above.
configureServer(server)
do {
// Launch the HTTP server.
try server.start()
} catch PerfectError.networkError(let err, let msg) {
print("Network error thrown: (err) (msg)")
}
Server Start
// Create HTTP server.
let server = HTTPServer()
// Register your own routes and handlers
var routes = Routes()
// Add the routes to the server.
server.addRoutes(routes)
// Set a listen port of 8181
server.serverPort = 8181
// Set a document root.
// This is optional. If you do not want to serve static content then do not set this.
// Setting the document root will automatically add a static file handler for the route /**
server.documentRoot = "./webroot"
// Gather command line options and further configure the server.
// Run the server with --help to see the list of supported arguments.
// Command line arguments will supplant any of the values set above.
configureServer(server)
do {
// Launch the HTTP server.
try server.start()
} catch PerfectError.networkError(let err, let msg) {
print("Network error thrown: (err) (msg)")
}
Server Start
// Create HTTP server.
let server = HTTPServer()
// Register your own routes and handlers
var routes = Routes()
// Add the routes to the server.
server.addRoutes(routes)
// Set a listen port of 8181
server.serverPort = 8181
// Set a document root.
// This is optional. If you do not want to serve static content then do not set this.
// Setting the document root will automatically add a static file handler for the route /**
server.documentRoot = "./webroot"
// Gather command line options and further configure the server.
// Run the server with --help to see the list of supported arguments.
// Command line arguments will supplant any of the values set above.
configureServer(server)
do {
// Launch the HTTP server.
try server.start()
} catch PerfectError.networkError(let err, let msg) {
print("Network error thrown: (err) (msg)")
}
Server Start
// Create HTTP server.
let server = HTTPServer()
// Register your own routes and handlers
var routes = Routes()
// Add the routes to the server.
server.addRoutes(routes)
// Set a listen port of 8181
server.serverPort = 8181
// Set a document root.
// This is optional. If you do not want to serve static content then do not set this.
// Setting the document root will automatically add a static file handler for the route /**
server.documentRoot = "./webroot"
// Gather command line options and further configure the server.
// Run the server with --help to see the list of supported arguments.
// Command line arguments will supplant any of the values set above.
configureServer(server)
do {
// Launch the HTTP server.
try server.start()
} catch PerfectError.networkError(let err, let msg) {
print("Network error thrown: (err) (msg)")
}
Server Start
Make
Router
// list
routes.add(method: .get, uri: "/list", handler: listHandler)
// login
routes.add(method: .post, uri: "/login", handler: loginHandler)
// get message
routes.add(method: .get, uri: "/message", handler: getMessageHandler)
// post message
routes.add(method: .post, uri: "/message", handler: postMessageHandler)
https://github.com/PerfectlySoft/PerfectExample-
URLRouting
GET Method
// listHandler
func listHandler(request: HTTPRequest, _ response: HTTPResponse) {
defer {
response.completed()
}
response.setHeader(.contentType, value: "application/json")
do {
let listArray: [String : Any] = [
"name1": 300,
"name2": 230.45,
"name3": 150
]
try response.setBody(json: listArray)
} catch let error as NSError {
print(error)
}
}
GET Method
curl -v -H "Accept: application/json" -H "Content-type: application/json" -
X GET http://0.0.0.0:8181/list
* Trying 0.0.0.0...
* Connected to 0.0.0.0 (127.0.0.1) port 8181 (#0)
> GET /list HTTP/1.1
> Host: 0.0.0.0:8181
> User-Agent: curl/7.43.0
> Accept: application/json
> Content-type: application/json
>
< HTTP/1.1 200 OK
< Content-Type: application/json
< Connection: Keep-Alive
< Content-Length: 40
<
* Connection #0 to host 0.0.0.0 left intact
{"name1":300,"name2":230.45,"name3":150}
GET Method
// check thread
let thread = Thread.current
print(thread)
[INFO] Starting HTTP server on 0.0.0.0:8181 with document root ./webroot
<NSThread: 0x7fab61c15530>{number = 2, name = (null)}
<NSThread: 0x7fab61e06cd0>{number = 3, name = (null)}
<NSThread: 0x7fab61f05290>{number = 4, name = (null)}
全てのリクエストが別のThreadで実行さ
れていることがわかる
POST Method
// loginHandler
func loginHandler(request: HTTPRequest, _ response: HTTPResponse) {
defer {
response.completed()
}
do {
let json = try request.postBodyString?.jsonDecode()
response.setHeader(.contentType, value: "application/json")
guard let decoded = json as? [String : Any] else { return }
let result: [String : Any] = decoded["user"].map {
["result": true, "user": $0]
} ?? ["result": false]
try response.setBody(json: result)
} catch let error as NSError {
print(error)
}
}
POST Method
curl -v -H "Accept: application/json" -H "Content-type: application/json" -
X POST -d '{"user": "tana"}' http://0.0.0.0:8181/login
* Trying 0.0.0.0...
* Connected to 0.0.0.0 (127.0.0.1) port 8181 (#0)
> POST /login HTTP/1.1
> Host: 0.0.0.0:8181
> User-Agent: curl/7.43.0
> Accept: application/json
> Content-type: application/json
> Content-Length: 16
>
* upload completely sent off: 16 out of 16 bytes
< HTTP/1.1 200 OK
< Content-Type: application/json
< Connection: Keep-Alive
< Content-Length: 29
<
* Connection #0 to host 0.0.0.0 left intact
{"result":true,"user":"tana"}
Database
Server Side? Swift
• Perfect Redis
• Perfect SQLite
• Perfect PostgreSQL
• Perfect MySQL
• Perfect MongoDB
• Perfect FileMaker
DB Connector
• Perfect Redis
• Perfect SQLite
• Perfect PostgreSQL
• Perfect MySQL
• Perfect MongoDB
• Perfect FileMaker
DB Connector
https://github.com/PerfectlySoft/Perfect-PostgreSQL
let package = Package(
name: "PerfectTemplate",
targets: [],
dependencies: [
.Package(
url: "https://github.com/PerfectlySoft/
Perfect-PostgreSQL.git",
versions: Version(0,0,0)..<Version(10,0,0))
]
)
Postgresql
プロジェクト直下のpackage.swiftに
Perfect-PostgresSQLを追加する
create table message (
id serial primary key,
message text,
created_at timestamp with time zone,
updated_at timestamp with time zone
);
• create message table
Create Table
GET Method
// get message
routes.add(method: .get, uri: "/message", handler: {
request, response in
defer {
response.completed()
}
do {
response.setHeader(.contentType, value: "application/json")
let connection = PGConnection()
let status = connection.connectdb(db)
let result = connection.exec(
statement: "select * FROM message order by updated_at desc")
…
// DB
let db = "postgresql://samplefuku:fukuoka@localhost:5432/exampledb"
GET Method…
let num = result.numTuples()
let messages: [[String : Any]] = (0..<num).map { x in
let t1 = result.getFieldString(tupleIndex: x, fieldIndex: 0)
let t2 = result.getFieldString(tupleIndex: x, fieldIndex: 1)
let t3 = result.getFieldString(tupleIndex: x, fieldIndex: 2)
let t4 = result.getFieldString(tupleIndex: x, fieldIndex: 3)
let message: [String : Any] = [
"id" : t1,
"message" : t2,
"created_at" : t3,
"updated_at" : t4
]
return message
}
result.clear()
connection.close()
try response.setBody(json: ["messages" : messages])
} catch let error as NSError {
print(error)
}
})
POST Method
// post message
routes.add(method: .post, uri: "/message", handler: {
request, response in
defer {
response.completed()
}
do {
let json = try request.postBodyString?.jsonDecode()
response.setHeader(.contentType, value: “application/json")
guard let decoded = json as? [String : Any] else { return }
…
POST Method
…
let result: [String : Any] = decoded["message"].map { message in
let connection = PGConnection()
let status = connection.connectdb(db)
let date = Date()
let createdAt = RFC3339DateFormatter.string(from: date)
let updatedAt = RFC3339DateFormatter.string(from: date)
let result = connection.exec(
statement: "insert into message (message, created_at,
updated_at) values($1, $2, $3)",
params: ["(message)", "(createdAt)", "(updatedAt)"])
result.clear()
connection.close()
return ["message" : message]
} ?? [:]
try response.setBody(json: result)
…
Demo
Deploy
http://perfect.org/heroku-buildpack-for-perfect-and-
swift.html
Heroku Buildpack for Perfect
and Swift
http://perfect.org/aws-buildpack-for-perfect-and-
swift.html
AWS Buildpack for Perfect and
Swift
AMI
AWSのマネージメントコンソールにログインし、
EC2のAMIから「us-east-1」リージョンにある
パブリックイメージから「perfect-ubuntu-1510」を
検索します。
AMI
セキュリティグループのインバウンドにHTTPを
追加しておく
AMI
$ sudo ssh -i ~/.ssh/xxxxx.pem ubuntu@xx.xxx.xx.xxx
AMI
$ wget https://swift.org/builds/development/ubuntu1510/swift-DEVELOPMENT-
SNAPSHOT-2016-08-26-a/swift-DEVELOPMENT-SNAPSHOT-2016-08-26-a-ubuntu15.10.tar.gz
$ tar xzf swift-DEVELOPMENT-SNAPSHOT-2016-08-26-a-ubuntu15.10.tar.gz
https://swift.org/download/#using-downloads
AMIにインストールされているのがSwift 2.2のため、
ビルドするためにサポートされているSwift 3.0の
SNAPSHOTを取得する
$ export PATH=./swift-DEVELOPMENT-SNAPSHOT-2016-08-26-a-ubuntu15.10/usr/bin:"$
{PATH}"
Build & Run
$ cd PerfectTemplate
$ swift build
$ .build/debug/PerfectTemplate
Demo
Appendix
Call Shell
// Commandline
func command(launchPath: String, arguments: [String]) -> String {
let task = Process()
task.launchPath = launchPath
task.arguments = arguments
let pipe = Pipe()
task.standardOutput = pipe
task.launch()
let data = pipe.fileHandleForReading.readDataToEndOfFile()
let output = String(
data: data,
encoding: String.Encoding.utf8)!
return output
}
let cl = command(launchPath: "/bin/echo", arguments: ["aaaa"])
Recap
• 絶賛発展途上
• クライアントサイドの開発者もWebAPI
の開発を経験しやすくなった
• コミッターになりやすい
Recap
Happy Swift life!!
One more thing...
http://dev.classmethod.jp/news/
developers-io-2016-in-fukuoka/
http://dev.classmethod.jp/news/job-
fair-20161007/
ありがとうございました🙇

More Related Content

KEY
Using and scaling Rack and Rack-based middleware
PDF
8 Minutes On Rack
PDF
Configuration Surgery with Augeas
PDF
httpd — Apache Web Server
PPTX
Puppet meetup testing
PDF
Rack Middleware
PDF
Chef or how to make computers do the work for us
PDF
Lesson 9. The Apache Web Server
Using and scaling Rack and Rack-based middleware
8 Minutes On Rack
Configuration Surgery with Augeas
httpd — Apache Web Server
Puppet meetup testing
Rack Middleware
Chef or how to make computers do the work for us
Lesson 9. The Apache Web Server

What's hot (20)

PPT
Deploy Rails Application by Capistrano
PDF
Puppet Camp Phoenix 2015: Managing Files via Puppet: Let Me Count The Ways (B...
PDF
Ansible - Swiss Army Knife Orchestration
PDF
Failsafe Mechanism for Yahoo Homepage
ODP
Aura Project for PHP
PDF
Replacing Squid with ATS
PDF
Ansible leveraging 2.0
PDF
Refactoring terraform
PDF
Oliver hookins puppetcamp2011
PDF
Getting Started with Ansible
PPTX
Introduction to ansible
PDF
Configuration management II - Terraform
PDF
Apache FTP Server Integration
PPTX
MySQL Monitoring using Prometheus & Grafana
PDF
Ansible loves Python, Python Philadelphia meetup
PDF
Exploring Async PHP (SF Live Berlin 2019)
PDF
Generators
PDF
#OktoCampus - Workshop : An introduction to Ansible
PDF
Vagrant for real (codemotion rome 2016)
PPT
2005_Structures and functions of Makefile
Deploy Rails Application by Capistrano
Puppet Camp Phoenix 2015: Managing Files via Puppet: Let Me Count The Ways (B...
Ansible - Swiss Army Knife Orchestration
Failsafe Mechanism for Yahoo Homepage
Aura Project for PHP
Replacing Squid with ATS
Ansible leveraging 2.0
Refactoring terraform
Oliver hookins puppetcamp2011
Getting Started with Ansible
Introduction to ansible
Configuration management II - Terraform
Apache FTP Server Integration
MySQL Monitoring using Prometheus & Grafana
Ansible loves Python, Python Philadelphia meetup
Exploring Async PHP (SF Live Berlin 2019)
Generators
#OktoCampus - Workshop : An introduction to Ansible
Vagrant for real (codemotion rome 2016)
2005_Structures and functions of Makefile
Ad

Viewers also liked (7)

PPTX
Server Side Swift
PDF
Enumはデキる子 ~ case .Success(let value): ~
PDF
Server-side Swift
PPTX
An introduction to Microservices
PPTX
An Introduction to OAuth 2
PDF
Server-side Swift
PDF
Authentication: Cookies vs JWTs and why you’re doing it wrong
Server Side Swift
Enumはデキる子 ~ case .Success(let value): ~
Server-side Swift
An introduction to Microservices
An Introduction to OAuth 2
Server-side Swift
Authentication: Cookies vs JWTs and why you’re doing it wrong
Ad

Similar to Server Side? Swift (20)

PDF
Server Side Swift with Swag
PDF
FrenchKit 2017: Server(less) Swift
PDF
Swift Summit 2017: Server Swift State of the Union
PDF
Networked APIs with swift
PDF
Server Side Swift: Vapor
PDF
Introduction to Nodejs
PDF
swift-nio のアーキテクチャーと RxHttpClient
PDF
Swift server-side-let swift2016
PPTX
Intro to Perfect - LA presentation
PDF
Rethinking Syncing at AltConf 2019
PDF
Ruby HTTP clients comparison
PPT
Iss letcure 7_8
PDF
Everybody Loves AFNetworking ... and So Can you!
PDF
Asynchronous Architectures for Implementing Scalable Cloud Services - Evan Co...
PDF
RPC to REST (Hypermedia)
PDF
Go for the paranoid network programmer, 2nd edition
PDF
Taming Cloud APIs with Swift
PDF
How to build a scalable SNS via Polling & Push
PDF
RESTful Web Applications with Google Go
PDF
Ruby MVC from scratch with Rack
Server Side Swift with Swag
FrenchKit 2017: Server(less) Swift
Swift Summit 2017: Server Swift State of the Union
Networked APIs with swift
Server Side Swift: Vapor
Introduction to Nodejs
swift-nio のアーキテクチャーと RxHttpClient
Swift server-side-let swift2016
Intro to Perfect - LA presentation
Rethinking Syncing at AltConf 2019
Ruby HTTP clients comparison
Iss letcure 7_8
Everybody Loves AFNetworking ... and So Can you!
Asynchronous Architectures for Implementing Scalable Cloud Services - Evan Co...
RPC to REST (Hypermedia)
Go for the paranoid network programmer, 2nd edition
Taming Cloud APIs with Swift
How to build a scalable SNS via Polling & Push
RESTful Web Applications with Google Go
Ruby MVC from scratch with Rack

More from Takaaki Tanaka (6)

PDF
Swiftをキめると 気持ちいい!
PDF
AndroidーiOS開発比較〜iOSエンジニアから見たAndroidのアレコレ〜
PDF
全部見せます!最前線エンジニアが語るBleアプリケーションのハマりどころ(i os)
PDF
Swift api design guidelines (dec 3, 2015)
PDF
モバイル開発者から見た サーバーレスアーキテクチャ
PDF
AddressBook to Contacts
Swiftをキめると 気持ちいい!
AndroidーiOS開発比較〜iOSエンジニアから見たAndroidのアレコレ〜
全部見せます!最前線エンジニアが語るBleアプリケーションのハマりどころ(i os)
Swift api design guidelines (dec 3, 2015)
モバイル開発者から見た サーバーレスアーキテクチャ
AddressBook to Contacts

Recently uploaded (20)

PPTX
Understanding_Digital_Forensics_Presentation.pptx
PPTX
ACSFv1EN-58255 AWS Academy Cloud Security Foundations.pptx
PDF
KodekX | Application Modernization Development
PDF
Unlocking AI with Model Context Protocol (MCP)
PPTX
sap open course for s4hana steps from ECC to s4
PDF
Encapsulation_ Review paper, used for researhc scholars
PDF
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
PDF
Machine learning based COVID-19 study performance prediction
PDF
NewMind AI Weekly Chronicles - August'25 Week I
PPTX
Programs and apps: productivity, graphics, security and other tools
PDF
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PPTX
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
PPTX
Big Data Technologies - Introduction.pptx
PDF
Spectral efficient network and resource selection model in 5G networks
PPTX
MYSQL Presentation for SQL database connectivity
PDF
Electronic commerce courselecture one. Pdf
PDF
MIND Revenue Release Quarter 2 2025 Press Release
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
PDF
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
Understanding_Digital_Forensics_Presentation.pptx
ACSFv1EN-58255 AWS Academy Cloud Security Foundations.pptx
KodekX | Application Modernization Development
Unlocking AI with Model Context Protocol (MCP)
sap open course for s4hana steps from ECC to s4
Encapsulation_ Review paper, used for researhc scholars
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
Machine learning based COVID-19 study performance prediction
NewMind AI Weekly Chronicles - August'25 Week I
Programs and apps: productivity, graphics, security and other tools
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
Big Data Technologies - Introduction.pptx
Spectral efficient network and resource selection model in 5G networks
MYSQL Presentation for SQL database connectivity
Electronic commerce courselecture one. Pdf
MIND Revenue Release Quarter 2 2025 Press Release
20250228 LYD VKU AI Blended-Learning.pptx
How UI/UX Design Impacts User Retention in Mobile Apps.pdf

Server Side? Swift

  • 1.  2016/09/10 H-LANE #hackt_h HACKER TACKLE Server Side? Swift
  • 3. • 田中 孝明 (Takaaki Tanaka) • クラスメソッド株式会社 • iOS アプリケーションエンジニア • @kongmingtrap • iOS Developer (Swift / Objective-C) • GyazSquare / GitHub
  • 7. Swift Swift is a powerful and intuitive programming language for macOS, iOS, watchOS and tvOS. Writing Swift code is interactive and fun, the syntax is concise yet expressive, and Swift includes modern features developers love. Swift code is safe by design, yet also produces software that runs lightning-fast.
  • 8. History of Swift • 0.x (2014/06) • 1.0 (2014/09) • 1.1 (2014/10) • 1.2 (2015/02) • 2.0 (2015/06) • 2.1 (2015/10) • 2.2 (2016/03) • 3.0 (2016/09)
  • 9. History of Swift • 0.x (2014/06) • 1.0 (2014/09) • 1.1 (2014/10) • 1.2 (2015/02) • 2.0 (2015/06) • 2.1 (2015/10) • 2.2 (2016/03) • 3.0 (2016/09) 黎明期
  • 10. History of Swift • 0.x (2014/06) • 1.0 (2014/09) • 1.1 (2014/10) • 1.2 (2015/02) • 2.0 (2015/06) • 2.1 (2015/10) • 2.2 (2016/03) • 3.0 (2016/09) 成長期
  • 11. History of Swift • 0.x (2014/06) • 1.0 (2014/09) • 1.1 (2014/10) • 1.2 (2015/02) • 2.0 (2015/06) • 2.1 (2015/10) • 2.2 (2016/03) • 3.0 (2016/09) 全盛期
  • 12. [swift-evolution] Looking back on Swift 3 and ahead to Swift 4 https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160725/025676.html ABI安定化など、Swift 3.0で実装予定だっ た機能が見送られ、Swift 4.0まで持ち越 される。。。
  • 13. Swift is Open Source https://developer.apple.com/swift/blog/?id=34
  • 14. Going Server-side with Swift Open Source https://developer.apple.com/videos/play/ wwdc2016/415/ WWDC2016
  • 17. Agenda • Server Side Swift frameworks • Environment construct • Make • Deploy
  • 18. Server Side Swift frameworks
  • 21. Perfect • Swift における Rails の立ち位置を目指す • 豊富なDB接続ライブラリ • Mustacheテンプレート • FastCGI + apache2 or Nginx
  • 23. VAPOR • Laraval like • シンプルに記述できることを目指す • ドキュメントが丁寧にまとめられている https://github.com/vapor/vapor
  • 25. KITURA • IBM製 • IBMのクラウドプラットフォームBluemixがSwiftに対 応 • サンドボックスで試すことができる • Swift関連の取り組みも熱心 https://github.com/IBM-Swift
  • 36. Build Xcode 8.0 or later OS X El Captan (10.11.6)
  • 37. $ swift —version Apple Swift version 3.0 (swiftlang-800.0.43.6 clang-800.0.38) Target: x86_64-apple-macosx10.9 $ xcode-select --switch /Applications/Xcode.app/Contents/Developer Build
  • 38. $ brew install openssl $ brew link openssl --force Build $ git clone https://github.com/PerfectlySoft/PerfectTemplate.git $ cd PerfectTemplate $ swift build $ .build/debug/PerfectTemplate
  • 40. // Create HTTP server. let server = HTTPServer() // Register your own routes and handlers var routes = Routes() // Add the routes to the server. server.addRoutes(routes) // Set a listen port of 8181 server.serverPort = 8181 // Set a document root. // This is optional. If you do not want to serve static content then do not set this. // Setting the document root will automatically add a static file handler for the route /** server.documentRoot = "./webroot" // Gather command line options and further configure the server. // Run the server with --help to see the list of supported arguments. // Command line arguments will supplant any of the values set above. configureServer(server) do { // Launch the HTTP server. try server.start() } catch PerfectError.networkError(let err, let msg) { print("Network error thrown: (err) (msg)") } Server Start
  • 41. // Create HTTP server. let server = HTTPServer() // Register your own routes and handlers var routes = Routes() // Add the routes to the server. server.addRoutes(routes) // Set a listen port of 8181 server.serverPort = 8181 // Set a document root. // This is optional. If you do not want to serve static content then do not set this. // Setting the document root will automatically add a static file handler for the route /** server.documentRoot = "./webroot" // Gather command line options and further configure the server. // Run the server with --help to see the list of supported arguments. // Command line arguments will supplant any of the values set above. configureServer(server) do { // Launch the HTTP server. try server.start() } catch PerfectError.networkError(let err, let msg) { print("Network error thrown: (err) (msg)") } Server Start
  • 42. // Create HTTP server. let server = HTTPServer() // Register your own routes and handlers var routes = Routes() // Add the routes to the server. server.addRoutes(routes) // Set a listen port of 8181 server.serverPort = 8181 // Set a document root. // This is optional. If you do not want to serve static content then do not set this. // Setting the document root will automatically add a static file handler for the route /** server.documentRoot = "./webroot" // Gather command line options and further configure the server. // Run the server with --help to see the list of supported arguments. // Command line arguments will supplant any of the values set above. configureServer(server) do { // Launch the HTTP server. try server.start() } catch PerfectError.networkError(let err, let msg) { print("Network error thrown: (err) (msg)") } Server Start
  • 43. // Create HTTP server. let server = HTTPServer() // Register your own routes and handlers var routes = Routes() // Add the routes to the server. server.addRoutes(routes) // Set a listen port of 8181 server.serverPort = 8181 // Set a document root. // This is optional. If you do not want to serve static content then do not set this. // Setting the document root will automatically add a static file handler for the route /** server.documentRoot = "./webroot" // Gather command line options and further configure the server. // Run the server with --help to see the list of supported arguments. // Command line arguments will supplant any of the values set above. configureServer(server) do { // Launch the HTTP server. try server.start() } catch PerfectError.networkError(let err, let msg) { print("Network error thrown: (err) (msg)") } Server Start
  • 44. // Create HTTP server. let server = HTTPServer() // Register your own routes and handlers var routes = Routes() // Add the routes to the server. server.addRoutes(routes) // Set a listen port of 8181 server.serverPort = 8181 // Set a document root. // This is optional. If you do not want to serve static content then do not set this. // Setting the document root will automatically add a static file handler for the route /** server.documentRoot = "./webroot" // Gather command line options and further configure the server. // Run the server with --help to see the list of supported arguments. // Command line arguments will supplant any of the values set above. configureServer(server) do { // Launch the HTTP server. try server.start() } catch PerfectError.networkError(let err, let msg) { print("Network error thrown: (err) (msg)") } Server Start
  • 45. Make
  • 46. Router // list routes.add(method: .get, uri: "/list", handler: listHandler) // login routes.add(method: .post, uri: "/login", handler: loginHandler) // get message routes.add(method: .get, uri: "/message", handler: getMessageHandler) // post message routes.add(method: .post, uri: "/message", handler: postMessageHandler) https://github.com/PerfectlySoft/PerfectExample- URLRouting
  • 47. GET Method // listHandler func listHandler(request: HTTPRequest, _ response: HTTPResponse) { defer { response.completed() } response.setHeader(.contentType, value: "application/json") do { let listArray: [String : Any] = [ "name1": 300, "name2": 230.45, "name3": 150 ] try response.setBody(json: listArray) } catch let error as NSError { print(error) } }
  • 48. GET Method curl -v -H "Accept: application/json" -H "Content-type: application/json" - X GET http://0.0.0.0:8181/list * Trying 0.0.0.0... * Connected to 0.0.0.0 (127.0.0.1) port 8181 (#0) > GET /list HTTP/1.1 > Host: 0.0.0.0:8181 > User-Agent: curl/7.43.0 > Accept: application/json > Content-type: application/json > < HTTP/1.1 200 OK < Content-Type: application/json < Connection: Keep-Alive < Content-Length: 40 < * Connection #0 to host 0.0.0.0 left intact {"name1":300,"name2":230.45,"name3":150}
  • 49. GET Method // check thread let thread = Thread.current print(thread) [INFO] Starting HTTP server on 0.0.0.0:8181 with document root ./webroot <NSThread: 0x7fab61c15530>{number = 2, name = (null)} <NSThread: 0x7fab61e06cd0>{number = 3, name = (null)} <NSThread: 0x7fab61f05290>{number = 4, name = (null)} 全てのリクエストが別のThreadで実行さ れていることがわかる
  • 50. POST Method // loginHandler func loginHandler(request: HTTPRequest, _ response: HTTPResponse) { defer { response.completed() } do { let json = try request.postBodyString?.jsonDecode() response.setHeader(.contentType, value: "application/json") guard let decoded = json as? [String : Any] else { return } let result: [String : Any] = decoded["user"].map { ["result": true, "user": $0] } ?? ["result": false] try response.setBody(json: result) } catch let error as NSError { print(error) } }
  • 51. POST Method curl -v -H "Accept: application/json" -H "Content-type: application/json" - X POST -d '{"user": "tana"}' http://0.0.0.0:8181/login * Trying 0.0.0.0... * Connected to 0.0.0.0 (127.0.0.1) port 8181 (#0) > POST /login HTTP/1.1 > Host: 0.0.0.0:8181 > User-Agent: curl/7.43.0 > Accept: application/json > Content-type: application/json > Content-Length: 16 > * upload completely sent off: 16 out of 16 bytes < HTTP/1.1 200 OK < Content-Type: application/json < Connection: Keep-Alive < Content-Length: 29 < * Connection #0 to host 0.0.0.0 left intact {"result":true,"user":"tana"}
  • 54. • Perfect Redis • Perfect SQLite • Perfect PostgreSQL • Perfect MySQL • Perfect MongoDB • Perfect FileMaker DB Connector
  • 55. • Perfect Redis • Perfect SQLite • Perfect PostgreSQL • Perfect MySQL • Perfect MongoDB • Perfect FileMaker DB Connector https://github.com/PerfectlySoft/Perfect-PostgreSQL
  • 56. let package = Package( name: "PerfectTemplate", targets: [], dependencies: [ .Package( url: "https://github.com/PerfectlySoft/ Perfect-PostgreSQL.git", versions: Version(0,0,0)..<Version(10,0,0)) ] ) Postgresql プロジェクト直下のpackage.swiftに Perfect-PostgresSQLを追加する
  • 57. create table message ( id serial primary key, message text, created_at timestamp with time zone, updated_at timestamp with time zone ); • create message table Create Table
  • 58. GET Method // get message routes.add(method: .get, uri: "/message", handler: { request, response in defer { response.completed() } do { response.setHeader(.contentType, value: "application/json") let connection = PGConnection() let status = connection.connectdb(db) let result = connection.exec( statement: "select * FROM message order by updated_at desc") … // DB let db = "postgresql://samplefuku:fukuoka@localhost:5432/exampledb"
  • 59. GET Method… let num = result.numTuples() let messages: [[String : Any]] = (0..<num).map { x in let t1 = result.getFieldString(tupleIndex: x, fieldIndex: 0) let t2 = result.getFieldString(tupleIndex: x, fieldIndex: 1) let t3 = result.getFieldString(tupleIndex: x, fieldIndex: 2) let t4 = result.getFieldString(tupleIndex: x, fieldIndex: 3) let message: [String : Any] = [ "id" : t1, "message" : t2, "created_at" : t3, "updated_at" : t4 ] return message } result.clear() connection.close() try response.setBody(json: ["messages" : messages]) } catch let error as NSError { print(error) } })
  • 60. POST Method // post message routes.add(method: .post, uri: "/message", handler: { request, response in defer { response.completed() } do { let json = try request.postBodyString?.jsonDecode() response.setHeader(.contentType, value: “application/json") guard let decoded = json as? [String : Any] else { return } …
  • 61. POST Method … let result: [String : Any] = decoded["message"].map { message in let connection = PGConnection() let status = connection.connectdb(db) let date = Date() let createdAt = RFC3339DateFormatter.string(from: date) let updatedAt = RFC3339DateFormatter.string(from: date) let result = connection.exec( statement: "insert into message (message, created_at, updated_at) values($1, $2, $3)", params: ["(message)", "(createdAt)", "(updatedAt)"]) result.clear() connection.close() return ["message" : message] } ?? [:] try response.setBody(json: result) …
  • 62. Demo
  • 68. AMI $ sudo ssh -i ~/.ssh/xxxxx.pem ubuntu@xx.xxx.xx.xxx
  • 69. AMI $ wget https://swift.org/builds/development/ubuntu1510/swift-DEVELOPMENT- SNAPSHOT-2016-08-26-a/swift-DEVELOPMENT-SNAPSHOT-2016-08-26-a-ubuntu15.10.tar.gz $ tar xzf swift-DEVELOPMENT-SNAPSHOT-2016-08-26-a-ubuntu15.10.tar.gz https://swift.org/download/#using-downloads AMIにインストールされているのがSwift 2.2のため、 ビルドするためにサポートされているSwift 3.0の SNAPSHOTを取得する $ export PATH=./swift-DEVELOPMENT-SNAPSHOT-2016-08-26-a-ubuntu15.10/usr/bin:"$ {PATH}"
  • 70. Build & Run $ cd PerfectTemplate $ swift build $ .build/debug/PerfectTemplate
  • 71. Demo
  • 73. Call Shell // Commandline func command(launchPath: String, arguments: [String]) -> String { let task = Process() task.launchPath = launchPath task.arguments = arguments let pipe = Pipe() task.standardOutput = pipe task.launch() let data = pipe.fileHandleForReading.readDataToEndOfFile() let output = String( data: data, encoding: String.Encoding.utf8)! return output } let cl = command(launchPath: "/bin/echo", arguments: ["aaaa"])
  • 74. Recap