Git Product home page Git Product logo

slimane's Introduction

Slimane

OverView

Slimane is an express inspired web framework for Swift that works on OSX and Ubuntu.

  • Completely Asynchronous
  • Unopinionated and Minimalist
  • Adopts Open Swift
  • Feature/Promise Support

A Work In Progress

Slimane is currently in active development.
Feel free to contribute, pull requests are welcome!

Attension

It works as a completely asynchronous and the core runtime is created with libuv.
So Don't stop the event loop with the CPU heavy tasks.
Guide of working with the cpu heavy tasks

Slimae Project Page ๐ŸŽ‰

Various types of libraries are available from here.

https://github.com/slimane-swift

Considering/In developing

  • Streaming Response
  • Deal with Mysql via asynchronous networking
  • Promise Support
  • Command line interface

Getting Started

Install Guide

Here is install guides for each operating systems

Documentation

Here is Documentation for Slimane.

Usage

Starting the application takes slight lines.

import Slimane

let app = Slimane()

app.get("/") { req, responder in
    responder {
      Response(body: "Welcome Slimane!")
    }
}

try! app.listen()

Example Project

https://github.com/slimane-swift/slimane-example

Routing

app.get("/articles/:id") { req, responder in
    responder {
        Response(body: "Article ID is: \(req.params["id"]!)")
    }
}

Methods

  • get
  • options
  • post
  • put
  • patch
  • delete

Middlewares

Middleware is functions that have access to the http request, the http response, and the next function in the application' s request-response cycle. We offers 3 types of registration ways for that.

See more to visit https://github.com/slimane-swift/Middleware

MiddlewareType

struct AccessLogMiddleware: MiddlewareType {
    func respond(req: Request, res: Response, next: MiddlewareChain) {
        print("[\(Suv.Time())] \(req.uri.path ?? "/")")
        next(.Chain(req, res))
    }
}

app.use(AccessLogMiddleware())

AsyncMiddleware

Can pass the Open-Swift's AsyncMiddleware confirming Middleware

struct AccessLogMiddleware: AsyncMiddleware {
    func respond(to request: Request, chainingTo next: AsyncResponder, result: (Void throws -> Response) -> Void) {
        print("[\(Suv.Time())] \(request.path ?? "/")")
        next.respond(to: request) { response in
            result {
                try response()
            }
        }
    }
}

app.use(AccessLogMiddleware())

Handy

app.use { req, res, next in
    print("[\(Suv.Time())] \(req.uri.path ?? "/")")
    next(.Chain(req, res))
}

Intercept Response

Can intercept response at the middleware with passing any values into the Response.body. It means respond soon and never reaches next middleware chains and the route.

app.use { req, res, next in
    var res = res
    res.body("I'm intercepted at the middleware")
    next(.Chain(req, res))
}

Request/Response

We are using S4.Request and S4.Response See more detail, please visit https://github.com/open-swift/S4

Static Files/Assets

Just register the Slimane.Static() into middleware chains

app.use(Slimane.Static(root: "/path/to/your/public"))

Cookie

request.cookies: Set<Cookie>

request.cookies is Readonly.

req.cookies["session-id"]

Cookie is declared in S4. See more to visit https://github.com/open-swift/S4

response.cookies: Set<AttributedCookie>

response.cookies is Writable.

let setCookie = AttributedCookie(....)
res.cookies = Set<setCookie>

AttributedCookie is declared in S4. See more to visit https://github.com/open-swift/S4

Session

Register SessionMiddleware into the middleware chains. See more detail for SessionMiddleware to visit https://github.com/slimane-swift/SessionMiddleware

import Slimane
import SessionMiddleware

let app = Slimane()

// SessionConfig
let sesConf = SessionConfig(
    secret: "my-secret-value",
    expires: 180,
    HTTPOnly: true
)

// Enable to use session in Slimane
app.use(SessionMiddleware(conf: sesConf))

app.get("/") { req, responder
    // set data into the session
    req.session["foo"] = "bar"

    req.session.id // show session id

    responder {
        Response()
    }
}

Available Session Stores

  • MemoryStore
  • SessionRedisStore

Body Data

Register BodyParser into the middleware chains.

app.use(BodyParser())

request.json Zewo.JSON

Can get parsed json data throgh the req.json when content-type is application/json

req.json?["foo"]

request.formData [String: String]

Can get parsed form data throgh the req.formData when content-type is application/x-www-form-urlencoded

req.formData?["foo"]

Views/Template Engines

Then, You can use render function in Slimane. and pass the render object to the custome label for Response initializer.

app.get("/render") { req, responder in
    responder {
        let render = Render(engine: MustacheViewEngine(templateData: ["foo": "bar"]), path "index")
        Response(custome: render)
    }
}

Create your own ViewEngine

Getting ready

Working with Cluster

A single instance of Slimane runs in a single thread. To take advantage of multi-core systems the user will sometimes want to launch a cluster of Slimane processes to handle the load.

Here is an easy example for working with Suv.Cluster

// For Cluster app
if Cluster.isMaster {
    for _ in 0..<OS.cpuCount {
        var worker = try! Cluster.fork(silent: false)
        observeWorker(&worker)
    }

    try! Slimane().listen()
} else {
    let app = Slimane()
    app.use("/") { req, responder in
        responder {
            Response(body: "Hello! I'm \(Process.pid)")
        }
    }

    try! app.listen()
}

IPC between Master and Worker Processes

Inter process message between master and workers

On Master

var worker = try! Cluster.fork(silent: false)

// Send message to the worker
worker.send(.Message("message from master"))

// Receive event from the worker
worker.on { event in
    if case .Message(let str) = event {
        print(str)
    }

    else if case .Online = event {
        print("Worker: \(worker.id) is online")
    }

    else if case .Exit(let status) = event {
        print("Worker: \(worker.id) is dead. status: \(status)")
        worker = try! Cluster.fork(silent: false)
        observeWorker(&worker)
    }
}

On Worker

// Receive event from the master
Process.on { event in
    if case .Message(let str) = event {
        print(str)
    }
}

// Send message to the master
Process.send(.Message("Hey!"))

Handling Errors

Easy to override Default Error Handler with replace app.errorHandler to your costume handler. All of the errors that occurred in Slimane's lifecycles are passed as first argument of errorHandler even RouteNotFound.

let app = Slimane()

app.errorHandler = myErrorHandler

func myErrorHandler(error: ErrorProtocol) -> Response {
    let response: Response
    switch error {
        case Costume.InvalidPrivilegeError
            response = Response(status: .forbidden, body: "Forbidden")
        case Costume.ResourceNotFoundError(let name)
            response = Response(status: .notFound, body: "\(name) is not found")
        default:
            response = Response(status: .badRequest, body: "\(error)")
    }

    return response
}

try! app.listen()

Note

Synchronous style ErrorHandler will be replaced to asynchronous.

Versions

Package.swift

import PackageDescription

let package = Package(
      name: "MyApp",
      dependencies: [
          .Package(url: "https://github.com/noppoMan/Slimane.git", majorVersion: 0, minor: 2),
      ]
)

License

Slimane is released under the MIT license. See LICENSE for details.

slimane's People

Contributors

noppoman avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.