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

More Server Side? Swift

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