Frank is a DSL for quickly writing web applications in Swift

Related tags

Networking Frank
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 Swift Multiplatform Single-threaded Non-blocking Web and Networking Framework
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

Super lightweight web framework in Swift based on SWSGI

Ambassador Super lightweight web framework in Swift based on SWSGI Features Super lightweight Easy to use, designed for UI automatic testing API mocki

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

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

Minimal web framework and middleware for Swift

Kunugi Kunugi(椚) is minimal web framework and middleware systems for Swift. This is inpired by Node.js' Koa. Kunugi doesn't provide http server its se

A web API client in Swift built using Async/Await

Get A modern web API client in Swift built using Async/Await and Actors. let cli

🌏 A zero-dependency networking solution for building modern and secure iOS, watchOS, macOS and tvOS applications.
🌏 A zero-dependency networking solution for building modern and secure iOS, watchOS, macOS and tvOS applications.

A zero-dependency networking solution for building modern and secure iOS, watchOS, macOS and tvOS applications. 🚀 TermiNetwork was tested in a produc

ROAD – Rapid Objective-C Applications Development

A set of reusable components taking advantage of extra dimension Attribute-Oriented Programming adds. Components Core - support for attributes, reflec

A resource based, protocol oriented networking library designed for pure-SwiftUI applications.

Monarch 👑 - WIP A resource based, protocol oriented networking library designed for pure-SwiftUI applications. Features: Async/Await Resource Based P

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
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
An awesome Swift HTML DSL library using result builders.

SwiftHtml An awesome Swift HTML DSL library using result builders. let doc = Document(.html5) { Html { Head { Meta()

Binary Birds 204 Dec 25, 2022
Open source SDK to quickly integrate subscriptions, stop worring about code maintenance, and getting advanced real-time data. Javascript / iOS glue framework

Open source SDK to quickly integrate subscriptions, stop worring about code maintenance, and getting advanced real-time data. Javascript / iOS glue framework

glassfy 5 Nov 7, 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
Swift implementation of WalletConnect v.2 protocol for native iOS applications

Wallet Connect v.2 - Swift Swift implementation of WalletConnect v.2 protocol for native iOS applications. Requirements iOS 13 XCode 13 Swift 5 Usage

WalletConnect 142 Jan 4, 2023
Robust Swift networking for web APIs

Conduit Conduit is a session-based Swift HTTP networking and auth library. Within each session, requests are sent through a serial pipeline before bei

Mindbody 52 Oct 26, 2022
💧 A server-side Swift web framework.

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

Vapor 22.4k Jan 2, 2023
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 Jan 6, 2023
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
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