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

Building practical web application with Slimane

Building practical web application with Slimane

Slide that is used in 2016 May 31 Tokyo server side swift meetup

Yuki Takei

June 01, 2016
Tweet

More Decks by Yuki Takei

Other Decks in Technology

Transcript

  1. B U I L D I N G P R

    A C T I C A L W E B A P P L I C AT I O N W I T H S L I M A N E 2 0 1 6 M A Y 3 1 T O K Y O S E R V E R S I D E S W I F T M E E T U P Y U K I TA K E I
  2. W H AT I S O P E N -

    S W I F T ? • C7: Core standards for Swift (Data, Stream etc…) • S4: HTTP standards for Swift (Request/Response etc..) • D5: Database standards for Swift. Open source cross project standards for Swift.
  3. W H AT S O F T WA R E

    S A R E N E E D E D T O B U I L D I T ? • HTTP Servers • Application Frameworks • Template Engines • Database Clients • Deployment
  4. S L I M A N E I S …

    • Express inspired Web Application Framework • 100% asynchronous with event loop backend (libuv) • Standalone HTTP Server • Faster • Moduler • Full managed asynchronous Stream, TCP, Pipe, FileSystem, Process, Timer etc.. • Adopt Open-Swift
  5. S P E C I F I C AT I

    O N • List issues • Get a single issue • Create issues • Post comments • Broadcast the comment to all clients via Web socket
  6. B A C K E N D S T R

    U C T U R E S pub/sub pub/sub reverse proxy app1 app2 github api ɾOS: Ubuntu(Vagrant) ɾCore: 4 ɾRAM: 2048MB
  7. F R O N T E N D • Template

    Engine: Mustache/lodash • JS Framework: jQuery • Css Framework: Bootstrap
  8. ɾvagrant up ɾlaunch single app ɾlogin ɾplay around(list issues, create

    an issue) ɾlaunch cluster app ɾweb socket ɾGraceful restart(Not implemented yet..) Menu
  9. • Get a Slimane server up • HTML Rendering •

    Deal with Github Api • Authentication • Web socket with Redis pub/sub • Asynchronous flow controll • Cluster/Worker • Graceful Restart(Not implemented yet…) Basic Technical Part of Github Issue Manager
  10. Get a Slimane server up import Slimane import JSON let

    app = Slimane() // access log app.use { req, res, next in print("[pid:\(Process.pid)]\t\(Time())\t\(req.path ?? "/")") next(.Chain(req, res)) } // Responsd to the simple json app.get("/") { req, responder in let json: JSON = ["foo": "bar"] responder { Response(body: JSONSerializer().serialize(json: json)) } } try! app.listen()
  11. HTML Rendering // app.swift import Slimane import MustacheViewEngine import Render

    extension Response { static func render(_ path: String, data: TemplateData = ["foo": "bar"]) -> Response { let render = Render(engine: MustacheViewEngine(templateData: data), path: path) return Response(custom: render) } } let app = Slimane() app.get("/") { req, responder in responder { Response.render("index", data: ["foo": "bar"]) } } try! app.listen() // index.mustache <html> <body> <h1>{{ foo }}</h1> </body> </html>
  12. Deal with Github API import Thrush import QWFuture struct CurlContext

    { let writeCallback: ([Byte]) -> () } return Promise<Data> { resolve, reject in let future = QWFuture<Data>(loop: self.loop) { (completion: (() throws -> Data) -> ()) in let handle = curl_easy_init() curlHelperSetOptString(handle, CURLOPT_URL, UnsafeMutablePointer(self.uri.buffer)) curlHelperSetOptBool(handle, CURLOPT_HTTPGET, CURL_TRUE) .................. var data = Data() let writeCallback = { (bytes: [Byte]) in data.append(contentsOf: bytes) } curlHelperSetOptWriteFunc(handle, context) { (buf, size, nMemb, privateData) -> Int in let ctx = UnsafePointer<CurlContext?>(privateData) let segsize = size * nMemb var bytes = [Byte]() for i in stride(from: 0, to: segsize, by: 1) { bytes.append(Byte(bitPattern: buf![i])) } ctx?.pointee?.writeCallback(bytes) return segsize } curl_easy_perform(handle) curl_easy_cleanup(handle) completion { data } } future.onSuccess { resolve($0) } future.onFailure { reject($0) }
  13. Deal with Github API Usage RestClient( method: .get, uri: "https://api.github.com/repos/noppoMan/Slimane/issues",

    body: JSONSerializer().serialize(json: ["body": data["body"]!.string!]) ) .send() .then { response in if 200..<300 ~= response.statusCode { success() } else { error() } } .failure { error in print(error) }