Created
June 12, 2014 19:17
-
-
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)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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