Frank is a DSL for quickly writing web applications in Swift

Overview

Frank

Frank is a DSL for quickly writing web applications in Swift with type-safe path routing.

Sources/main.swift
import Frank

// Handle GET requests to path /
get { request in
  return "Hello World"
}

// Handle GET requests to path /users/{username}
get("users", *) { (request, username: String) in
  return "Hello \(username)"
}
Package.swift
import PackageDescription

let package = Package(
  name: "Hello",
  dependencies: [
    .Package(url: "https://github.com/kylef/Frank.git", majorVersion: 0, minor: 4)
  ]
)

Then build, and run it via:

$ swift build --configuration release
$ .build/release/Hello
[2016-01-25 07:13:21 +0000] [25678] [INFO] Listening at http://0.0.0.0:8000 (25678)
[2016-01-25 07:13:21 +0000] [25679] [INFO] Booting worker process with pid: 25679

Check out the full example which can be deployed to Heroku.

Usage

Routes

Routes are constructed with passing your path split by slashes / as separate arguments to the HTTP method (e.g. get, post etc) functions.

For example, to match a path of /users/kyle/followers you can use the following:

get("users", "kyle", "followers") { request in

}

You may pass path components along with wildcard (*) to match variables in paths. The wildcard is a placemarker to annotate where the variable path components are in your path. Frank allows you to use any number of wildcards in any place of the path, allowing you to match all paths.

The wildcards will map directly to parameters in the path and the variables passed into your callback. Wildcard parameters are translated to the type specified in your closure.

// /users/{username}
get("users", *) { (request, username: String) in
  return "Hi \(username)"
}

// /users/{username}/followers
get("users", *, "followers") { (request, username: String) in
  return "\(username) has 5 followers"
}

You may place any type that conforms to ParameterConvertible in your callback, this allows the types to be correctly converted to your type or user will face a 404 since the URL will be invalid.

// /users/{userid}
get("users", *) { (request, userid: Int) in
  return "Hi user with ID: \(userid)"
}
Custom Parameter Types

Wildcard parameters may be of any type that conforms to ParameterConvertible, this allows you to match against custom types providing you conform to ParameterConvertible.

For example, we can create a Status enum which can be Open or Closed which conforms to ParameterConvertible:

enum Status : ParameterConvertible {
  case open
  case closed

  init?(parser: ParameterParser) {
    switch parser.shift() ?? "" {
      case "open":
        self = .open
      case "closed":
        self = .closed
      default:
        return nil
    }
  }
}

get("issues", *) { (request, status: Status) in
  return "Issues using status: \(status)"
}
Adding routes

Routes are matched in the order they are defined. The first route that matches the request is invoked.

get {
  ...
}

put {
  ...
}

patch {
  ...
}

delete {
  ...
}

head {
  ...
}

options {
  ...
}

Return Values

The return value of route blocks takes a type that conforms to the ResponseConvertible protocol, which means you can make any type Response Convertible. For example, you can return a simple string:

get {
  return "Hello World"
}

Return a full response:

get {
  return Response(.ok, headers: ["Custom-Header": "value"])
}

post {
  return Response(.created, content: "User created")
}

Templates

Stencil

You can easily use the Stencil template language with Frank. For example, you can create a convenience function to render templates (called stencil):

import Stencil
import Inquiline
import PathKit


func stencil(path: String, _ context: [String: Any]? = nil) -> ResponseConvertible {
  do {
    let template = try Template(path: Path(path))
    let body = try template.render(Context(dictionary: context))
    return Response(.ok, headers: [("Content-Type", "text/html")], content: body)
  } catch {
    return Response(.internalServerError)
  }
}

Which can easily be called from your route to render a template:

get {
  return stencil("hello.html", ["user": "world"])
}
hello.swift
<html>
  <body>
    Hello {{ user }}!
  </body>
</html>

Nest

Frank is design around the Nest Swift Web Server Gateway Interface, which allows you to use any Nest-compatible web servers. The exposed call function is a Nest compatible application which can be passed to a server of your choice.

import Frank

get {
  return "Custom Server"
}

// Pass "call" to your HTTP server
serve(call)
You might also like...
A small, lightweight, embeddable HTTP server for Mac OS X or iOS applications

CocoaHTTPServer CocoaHTTPServer is a small, lightweight, embeddable HTTP server for Mac OS X or iOS applications. Sometimes developers need an embedde

Server-side Swift. The Perfect core toolset and framework for Swift Developers. (For mobile back-end development, website and API development, and more…)

Perfect: Server-Side Swift 简体中文 Perfect: Server-Side Swift Perfect is a complete and powerful toolbox, framework, and application server for Linux, iO

Swift backend / server framework (Pure Swift, Supports Linux)

NetworkObjects NetworkObjects is a #PureSwift backend. This framework compiles for OS X, iOS and Linux and serves as the foundation for building power

Simple server APIs in Swift

Simple server APIs in Swift

 🪶 Feather is a modern Swift-based content management system powered by Vapor 4.
🪶 Feather is a modern Swift-based content management system powered by Vapor 4.

Feather CMS 🪶 🪶 Feather is a modern Swift-based content management system powered by Vapor 4. 💬 Click to join the chat on Discord. Requirements To

A dockerized microservice written in Swift using Vapor.

price-calculation-service-swift This is an example project for a university project. It uses Vapor to serve a microservice written in Swift. The point

Tiny http server engine written in Swift programming language.

What is Swifter? Tiny http server engine written in Swift programming language. Branches * stable - lands on CocoaPods and others. Supports the latest

Swift HTTP server using the pre-fork worker model

Curassow Curassow is a Swift Nest HTTP Server. It uses the pre-fork worker model and it's similar to Python's Gunicorn and Ruby's Unicorn. It exposes

HTTP Implementation for Swift on Linux and Mac OS X

Swift HTTP Server Simple HTTP implementation for Swift using POSIX socket API. Running on Mac OS X and Linux. For Mac users: You can install new Swift

Comments
  • Static Assets?

    Static Assets?

    Thinking of writing a middleware to serve up static assets (unless something already exists?), but I'm unsure how this plugs into Frank. Can you point me in the right direction?

    opened by subdigital 3
  • How would you daemonize?

    How would you daemonize?

    I see that this uses Curassow by default. In a Curassow application you can pass --daemonize when running to have it run in the background. Why I do this with a Frank application, it tells me the only options are --timeout, --workers, and --bind.

    opened by subdigital 2
  • Segfault (infinite recursion) in Frank

    Segfault (infinite recursion) in Frank

    Hey, I encountered (probably) a bug in Frank, where get(String, Closure) is calling itself and eventually crashing with a segfault. Here's my bare project which already shows it, just run make run to run the project and make debug to debug with lldb. https://github.com/czechboy0/ekg-swift

    Please let me know if Frank is fine and I'm just doing something wrong, thanks!

    opened by czechboy0 2
  • Add support for extracting variables from paths

    Add support for extracting variables from paths

    For example:

    get("/user/{username}") { request, args in
      return "Hello \(args[0])"
    }
    

    This would require URITemplate's extract to be implemented on Linux.

    opened by kylef 0
Owner
Kyle Fuller Archive
Older / Less maintained projects
Kyle Fuller Archive
Sinatra-like DSL for developing web apps in Swift

Swiftra Swiftra is a library that provides DSLs like Sinatra. System Requirements DEVELOPMENT-SNAPSHOT-2016-02-08-a Example See swiftra-example. impor

Shun Takebayashi 262 Jun 29, 2022
Lightweight library for web server applications in Swift on macOS and Linux powered by coroutines.

Why Zewo? • Support • Community • Contributing Zewo Zewo is a lightweight library for web applications in Swift. What sets Zewo apart? Zewo is not a w

Zewo 1.9k Dec 22, 2022
Swift Express is a simple, yet unopinionated web application server written in Swift

Documentation <h5 align="right"><a href="http://demo.swiftexpress.io/">Live ?? server running Demo <img src="https://cdn0.iconfinder.com/data/icons/

Crossroad Labs 850 Dec 2, 2022
💧 A server-side Swift HTTP web framework.

Vapor is an HTTP web framework for Swift. It provides a beautifully expressive and easy-to-use foundation for your next website, API, or cloud project

Vapor 22.4k Jan 3, 2023
A minimal, fast and unopinionated web framework for Swift

![Fire Image] (http://i.imgur.com/1qR6Nl4.png) Blackfire An extremely fast Swift web framework ?? Getting Started If you're familiar with express.js t

Elliott Minns 908 Dec 2, 2022
libuv base Swift web HTTP server framework

Notice Trevi now open a Trevi Community. Yoseob/Trevi project split up into respective Trevi, lime, middlewares and sys packages at our community. If

leeyoseob 46 Jan 29, 2022
A Swift web framework and HTTP server.

A Swift Web Framework and HTTP Server Summary Kitura is a web framework and web server that is created for web services written in Swift. For more inf

Kitura 7.6k Dec 27, 2022
A Ruby on Rails inspired Web Framework for Swift that runs on Linux and OS X

IMPORTANT! We don't see any way how to make web development as great as Ruby on Rails or Django with a very static nature of current Swift. We hope th

Saulius Grigaitis 2k Dec 5, 2022
High Performance (nearly)100% Swift Web server supporting dynamic content.

Dynamo - Dynamic Swift Web Server Starting this project the intention was to code the simplest possible Web Server entirely in Swift. Unfortunately I

John Holdsworth 68 Jul 25, 2022
A Swift Multiplatform Single-threaded Non-blocking Web and Networking Framework

Serverside non-blocking IO in Swift Ask questions in our Slack channel! Lightning (formerly Edge) Node Lightning is an HTTP Server and TCP Client/Serv

SkyLab 316 Oct 6, 2022