Skip to content

Instantly share code, notes, and snippets.

@jarsen
Created June 12, 2014 19:17
Show Gist options
  • Save jarsen/b1d77ba30e112267253a to your computer and use it in GitHub Desktop.
Save jarsen/b1d77ba30e112267253a to your computer and use it in GitHub Desktop.
TinyWeb program designed to run in a playground. Adapted from the OO java example in Functional Programming Patterns in Scala and Clojure (Pragmatic Bookshelf)
// TinyWeb OOP(ish) Style
import Foundation
class HTTPResponse {
let body: String
let responseCode: Int
init(body: String, responseCode: Int) {
self.body = body
self.responseCode = responseCode
}
}
class HTTPRequest {
let headers: Dictionary<String, String>
let body: String
let path: String
init(headers: Dictionary<String, String>, body: String, path: String) {
self.headers = headers
self.body = body
self.path = path
}
}
protocol View {
func render(model: Dictionary<String, String[]>) -> String
}
protocol RenderingStrategy {
func renderView(model: Dictionary<String, String[]>) -> String
}
class StrategyView : View {
let viewRenderer: RenderingStrategy
init(viewRenderer: RenderingStrategy) {
self.viewRenderer = viewRenderer
}
func render(model: Dictionary<String, String[]>) -> String {
return viewRenderer.renderView(model)
}
}
protocol Controller {
func handleRequest(request: HTTPRequest) -> HTTPResponse
}
class TemplateController : Controller {
let view: View
init(view: View) {
self.view = view
}
func handleRequest(request: HTTPRequest) -> HTTPResponse {
let responseCode = 200
var responseBody: String
if let model = doRequest(request) {
responseBody = view.render(model)
} else {
responseBody = "Exception while rendering"
}
return HTTPResponse(body: responseBody, responseCode: responseCode)
}
func doRequest(request: HTTPRequest) -> Dictionary<String, String[]>? {
return Dictionary<String, String[]>()
}
}
protocol Filter {
func doFilter(request: HTTPRequest) -> HTTPRequest
}
class TinyWeb {
let controllers: Dictionary<String, Controller>
let filters: Filter[]
init(controllers: Dictionary<String, Controller>, filters: Filter[]) {
self.controllers = controllers
self.filters = filters
}
func handleRequest(request: HTTPRequest) -> HTTPResponse? {
var currentRequest = request
for filter in self.filters {
currentRequest = filter.doFilter(currentRequest)
}
if let controller = controllers[currentRequest.path] {
return controller.handleRequest(request)
} else {
return nil
}
}
}
class GreetingController : TemplateController {
func generateGreetings(namesCommaSeparated: String) -> String[] {
let names = namesCommaSeparated.componentsSeparatedByString(",")
var greetings = String[]()
for name in names {
greetings.append(self.makeGreeting(name))
}
return greetings
}
func makeGreeting(name: String) -> String {
let greetings = ["Hello", "Greetings", "Saluations", "Hola"]
let randomIndex = Int(arc4random() % 4)
let greeting = greetings[randomIndex] + ", " + name
return greeting
}
override func doRequest(request: HTTPRequest) -> Dictionary<String, String[]>? {
var helloModel = Dictionary<String, String[]>()
helloModel["greetings"] = generateGreetings(request.body)
return helloModel
}
}
class GreetingRenderingStrategy : RenderingStrategy {
func renderView(model: Dictionary<String, String[]>) -> String {
if let greetings = model["greetings"] {
var responseBody = "<h1>Friendly Greetings:</h1>\n"
for greeting in greetings {
responseBody += "<p>\(greeting)</p>"
}
return responseBody
} else {
return ""
}
}
}
class LoggingFilter : Filter {
func doFilter(request: HTTPRequest) -> HTTPRequest {
println("In Logging Filter - request for path: \(request.path)")
return request
}
}
let viewRenderer = GreetingRenderingStrategy()
let greetingView = StrategyView(viewRenderer: viewRenderer)
let greetingController = GreetingController(view: greetingView)
let controllers: Dictionary<String, Controller> = ["greeting/" : greetingController]
let filters: Filter[] = [LoggingFilter()]
let tinyWeb = TinyWeb(controllers: controllers, filters: filters)
let testRequest = HTTPRequest(headers: ["X-Example" : "exampleHeader"], body: "Mike,Joe,John,Steve", path: "greeting/")
let testResponse = tinyWeb.handleRequest(testRequest)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment