Slide 1

Slide 1 text

ɹ2016/09/10 H-LANE #hackt_h HACKER TACKLE Server Side? Swift

Slide 2

Slide 2 text

About Me

Slide 3

Slide 3 text

• ాத ޹໌ (Takaaki Tanaka) • Ϋϥεϝιουגࣜձࣾ • iOS ΞϓϦέʔγϣϯΤϯδχΞ • @kongmingtrap • iOS Developer (Swift / Objective-C) • GyazSquare / GitHub

Slide 4

Slide 4 text

Me and Fukuoka

Slide 5

Slide 5 text

ͪΐ͏Ͳ1೥લ·ͰॅΜͰ͍·ͨ͠

Slide 6

Slide 6 text

Summary of Swift

Slide 7

Slide 7 text

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.

Slide 8

Slide 8 text

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)

Slide 9

Slide 9 text

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) ᴈ໌ظ

Slide 10

Slide 10 text

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) ੒௕ظ

Slide 11

Slide 11 text

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) શ੝ظ

Slide 12

Slide 12 text

[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 "#*҆ఆԽͳͲɺ4XJGUͰ࣮૷༧ఆͩͬ ͨػೳ͕ݟૹΒΕɺ4XJGU·Ͱ࣋ͪӽ ͞ΕΔɻɻɻ

Slide 13

Slide 13 text

Swift is Open Source IUUQTEFWFMPQFSBQQMFDPNTXJGUCMPH JE

Slide 14

Slide 14 text

(PJOH4FSWFSTJEFXJUI4XJGU0QFO4PVSDF IUUQTEFWFMPQFSBQQMFDPNWJEFPTQMBZ XXED WWDC2016

Slide 15

Slide 15 text

Architecture IUUQTEFWFMPQFSBQQMFDPNWJEFPTQMBZ XXED

Slide 16

Slide 16 text

Architecture IUUQTEFWFMPQFSBQQMFDPNWJEFPTQMBZ XXED

Slide 17

Slide 17 text

Agenda • Server Side Swift frameworks • Environment construct • Make • Deploy

Slide 18

Slide 18 text

Server Side Swift frameworks

Slide 19

Slide 19 text

No content

Slide 20

Slide 20 text

IUUQTHJUIVCDPN1FSGFDUMZ4PGU1FSGFDU Perfect

Slide 21

Slide 21 text

Perfect w 4XJGUʹ͓͚Δ`3BJMT`ͷཱͪҐஔΛ໨ࢦ͢ w ๛෋ͳ%#઀ଓϥΠϒϥϦ w .VTUBDIFςϯϓϨʔτ w 'BTU$(*BQBDIFPS/HJOY

Slide 22

Slide 22 text

IUUQRVUIFPSZJP VAPOR

Slide 23

Slide 23 text

VAPOR w -BSBWBMMJLF w γϯϓϧʹهड़Ͱ͖Δ͜ͱΛ໨ࢦ͢ w υΩϡϝϯτ͕ஸೡʹ·ͱΊΒΕ͍ͯΔ IUUQTHJUIVCDPNWBQPSWBQPS

Slide 24

Slide 24 text

IUUQTEFWFMPQFSJCNDPNTXJGULJUVSB KITURA

Slide 25

Slide 25 text

KITURA w *#.੡ w *#.ͷΫϥ΢υϓϥοτϑΥʔϜ#MVFNJY͕4XJGUʹର Ԡ w αϯυϘοΫεͰࢼ͢͜ͱ͕Ͱ͖Δ w 4XJGUؔ࿈ͷऔΓ૊Έ΋೤৺ IUUQTHJUIVCDPN*#.4XJGU

Slide 26

Slide 26 text

IUUQXXX[FXPJP Zewo

Slide 27

Slide 27 text

Zewo w ๛෋ͳύοέʔδ਺ w #BTF$PNQPOFOUTΛ7BQPSͱೖΕସ͑Δ͜ͱ͕Ͱ͖ Δ IUUQTHJUIVCDPN;FXP

Slide 28

Slide 28 text

IUUQTHJUIVCDPNOFDPMU4XJGUPO Swifton

Slide 29

Slide 29 text

IUUQTHJUIVCDPNOFDPMU4XJGUPO Swifton w 3VCZPO3BJMTMJLF

Slide 30

Slide 30 text

IUUQTHJUIVCDPNOPQQP.BO4MJNBOF Slimane

Slide 31

Slide 31 text

IUUQTHJUIVCDPNOPQQP.BO Slimane w FYQSFTTʹΠϯεύΠΞ w ϚΠΫϩϑϨʔϜϫʔΫʴ)551αʔόʔ w :VLJ5BLFJ͞Μ࡞੒

Slide 32

Slide 32 text

Environment construct

Slide 33

Slide 33 text

ࠓճͷσϞͰ࠾༻

Slide 34

Slide 34 text

TUBSPWFS

Slide 35

Slide 35 text

Perfect Template IUUQTHJUIVCDPN1FSGFDUMZ4PGU1FSGFDU5FNQMBUFHJU

Slide 36

Slide 36 text

Build 9DPEFPSMBUFS 049&M$BQUBO

Slide 37

Slide 37 text

$ 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

Slide 38

Slide 38 text

$ brew install openssl $ brew link openssl --force Build $ git clone https://github.com/PerfectlySoft/PerfectTemplate.git $ cd PerfectTemplate $ swift build $ .build/debug/PerfectTemplate

Slide 39

Slide 39 text

No content

Slide 40

Slide 40 text

// 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

Slide 41

Slide 41 text

// 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

Slide 42

Slide 42 text

// 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

Slide 43

Slide 43 text

// 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

Slide 44

Slide 44 text

// 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

Slide 45

Slide 45 text

Make

Slide 46

Slide 46 text

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) IUUQTHJUIVCDPN1FSGFDUMZ4PGU1FSGFDU&YBNQMF 63-3PVUJOH

Slide 47

Slide 47 text

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) } }

Slide 48

Slide 48 text

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}

Slide 49

Slide 49 text

GET Method // check thread let thread = Thread.current print(thread) [INFO] Starting HTTP server on 0.0.0.0:8181 with document root ./webroot {number = 2, name = (null)} {number = 3, name = (null)} {number = 4, name = (null)} શͯͷϦΫΤετ͕ผͷ5ISFBEͰ࣮ߦ͞ Ε͍ͯΔ͜ͱ͕Θ͔Δ

Slide 50

Slide 50 text

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) } }

Slide 51

Slide 51 text

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"}

Slide 52

Slide 52 text

Database

Slide 53

Slide 53 text

No content

Slide 54

Slide 54 text

w 1FSGFDU3FEJT w 1FSGFDU42-JUF w 1FSGFDU1PTUHSF42- w 1FSGFDU.Z42- w 1FSGFDU.POHP%# w 1FSGFDU'JMF.BLFS DB Connector

Slide 55

Slide 55 text

w 1FSGFDU3FEJT w 1FSGFDU42-JUF w 1FSGFDU1PTUHSF42- w 1FSGFDU.Z42- w 1FSGFDU.POHP%# w 1FSGFDU'JMF.BLFS DB Connector IUUQTHJUIVCDPN1FSGFDUMZ4PGU1FSGFDU1PTUHSF42-

Slide 56

Slide 56 text

let package = Package( name: "PerfectTemplate", targets: [], dependencies: [ .Package( url: "https://github.com/PerfectlySoft/ Perfect-PostgreSQL.git", versions: Version(0,0,0)..

Slide 57

Slide 57 text

create table message ( id serial primary key, message text, created_at timestamp with time zone, updated_at timestamp with time zone ); w DSFBUFNFTTBHFUBCMF Create Table

Slide 58

Slide 58 text

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"

Slide 59

Slide 59 text

GET Method … let num = result.numTuples() let messages: [[String : Any]] = (0..

Slide 60

Slide 60 text

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 } …

Slide 61

Slide 61 text

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) …

Slide 62

Slide 62 text

Demo

Slide 63

Slide 63 text

Deploy

Slide 64

Slide 64 text

IUUQQFSGFDUPSHIFSPLVCVJMEQBDLGPSQFSGFDUBOE TXJGUIUNM Heroku Buildpack for Perfect and Swift

Slide 65

Slide 65 text

IUUQQFSGFDUPSHBXTCVJMEQBDLGPSQFSGFDUBOE TXJGUIUNM AWS Buildpack for Perfect and Swift

Slide 66

Slide 66 text

AMI "84ͷϚωʔδϝϯτίϯιʔϧʹϩάΠϯ͠ɺ &$ͷ".*͔ΒʮVTFBTUʯϦʔδϣϯʹ͋Δ ύϒϦοΫΠϝʔδ͔ΒʮQFSGFDUVCVOUVʯΛ ݕࡧ͠·͢ɻ

Slide 67

Slide 67 text

AMI ηΩϡϦςΟάϧʔϓͷΠϯό΢ϯυʹ)551Λ ௥Ճ͓ͯ͘͠

Slide 68

Slide 68 text

AMI $ sudo ssh -i ~/.ssh/xxxxx.pem [email protected]

Slide 69

Slide 69 text

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 IUUQTTXJGUPSHEPXOMPBEVTJOHEPXOMPBET ".*ʹΠϯετʔϧ͞Ε͍ͯΔͷ͕4XJGUͷͨΊɺ Ϗϧυ͢ΔͨΊʹαϙʔτ͞Ε͍ͯΔ4XJGUͷ 4/"14)05Λऔಘ͢Δ $ export PATH=./swift-DEVELOPMENT-SNAPSHOT-2016-08-26-a-ubuntu15.10/usr/bin:"$ {PATH}"

Slide 70

Slide 70 text

Build & Run $ cd PerfectTemplate $ swift build $ .build/debug/PerfectTemplate

Slide 71

Slide 71 text

Demo

Slide 72

Slide 72 text

Appendix

Slide 73

Slide 73 text

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"])

Slide 74

Slide 74 text

Recap

Slide 75

Slide 75 text

w ઈࢍൃల్্ w ΫϥΠΞϯταΠυͷ։ൃऀ΋8FC"1* ͷ։ൃΛܦݧ͠΍͘͢ͳͬͨ w ίϛολʔʹͳΓ΍͍͢ Recap

Slide 76

Slide 76 text

Happy Swift life!!

Slide 77

Slide 77 text

One more thing...

Slide 78

Slide 78 text

IUUQEFWDMBTTNFUIPEKQOFXT EFWFMPQFSTJPJOGVLVPLB

Slide 79

Slide 79 text

IUUQEFWDMBTTNFUIPEKQOFXTKPC GBJS

Slide 80

Slide 80 text

͋Γ͕ͱ͏͍͟͝·ͨ͠