Upgrade to Pro — share decks privately, control downloads, hide ads and more …

More Server Side? Swift

Takaaki Tanaka
September 28, 2016

More Server Side? Swift

AKIBA.swift 第5回での発表資料です

Takaaki Tanaka

September 28, 2016
Tweet

More Decks by Takaaki Tanaka

Other Decks in Technology

Transcript

  1. • ాத ޹໌ (Takaaki Tanaka) • Ϋϥεϝιουגࣜձࣾ • iOS ΞϓϦέʔγϣϯΤϯδχΞ

    • @kongmingtrap • iOS Developer (Swift / Objective-C) • GyazSquare / GitHub
  2. $ 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
  3. $ brew install openssl $ brew link openssl --force Build

    $ git clone https://github.com/PerfectlySoft/PerfectTemplate.git $ cd PerfectTemplate $ swift build $ .build/debug/PerfectTemplate
  4. 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
  5. 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) } }
  6. 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}
  7. 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)} શͯͷϦΫΤετ͕ผͷ5ISFBEͰ࣮ߦ͞ Ε͍ͯΔ͜ͱ͕Θ͔Δ
  8. 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) } }
  9. 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"}
  10. w 1FSGFDU3FEJT w 1FSGFDU42-JUF w 1FSGFDU1PTUHSF42- w 1FSGFDU.Z42- w 1FSGFDU.POHP%#

    w 1FSGFDU'JMF.BLFS DB Connector IUUQTHJUIVCDPN1FSGFDUMZ4PGU1FSGFDU1PTUHSF42-
  11. 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 ϓϩδΣΫτ௚ԼͷQBDLBHFTXJGUʹ 1FSGFDU1PTUHSFT42-Λ௥Ճ͢Δ
  12. 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
  13. 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"
  14. 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) } })
  15. 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 } …
  16. 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) …
  17. let package = Package( name: "PerfectTemplate", targets: [], dependencies: [

    .Package(url: "https://github.com/PerfectlySoft/Perfect- HTTPServer.git", versions: Version(0,0,0)..<Version(10,0,0)), .Package(url: "https://github.com/PerfectlySoft/Perfect- PostgreSQL.git", versions: Version(0,0,0)..<Version(10,0,0)), .Package(url: "https://github.com/ikesyo/Himotoki.git", versions: Version(0,0,0)..<Version(10,0,0)) ] )
  18. struct PostMessage: Decodable { let message: String // MARK: Decodable

    static func decode(_ e: Extractor) throws -> PostMessage { return try PostMessage( message: e <| "message" ) } } POST Method
  19. // 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") let message: PostMessage? = try? PostMessage.decodeValue(json) let result: [String : Any] = 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.message)", "\(createdAt)", "\(updatedAt)"]) result.clear() connection.close() return ["message" : message.message] } ?? [:] try response.setBody(json: result) } catch let error as NSError { print(error) } })
  20. struct Message: Decodable { let id: String? let message: String

    let created_at: String let updated_at: String // MARK: Decodable static func decode(_ e: Extractor) throws -> Message { return try Message( id: e <|? "id", message: e <| "message", created_at: e <| "created_at", updated_at: e <| "updated_at" ) } } struct Messages: Decodable { let messages: [Message] // MARK: Decodable static func decode(_ e: Extractor) throws -> Messages { return try Messages( messages: e <|| ["messages"] ) } } GET Method
  21. // get message routes.add(method: .get, uri: "/message", handler: { request,

    response in defer { response.completed() } do { print(request.params()) 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") let num = result.numTuples() let dict: [[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 } let json: [String : Any] = ["messages" : dict] let messages: Messages? = try? Messages.decodeValue(json) result.clear() connection.close() try response.setBody(json: json) } catch let error as NSError { print(error) } })