-
-
Save casualjim/1204395 to your computer and use it in GitHub Desktop.
This file contains 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
trait HandlerArgs { | |
def isInitial: Boolean | |
} | |
case object InitialArgs { val isInitial = true } | |
case object ContinuationArgs { val isInitial = false } | |
class Handler extends ((Request, HandlerArgs) => Response) | |
class Middleware extends (Handler => Handler) | |
object Server { | |
type ResponseWriter = Response => Result | |
val handler: Handler | |
object Executor { | |
@tailrec | |
def apply(handle: Handler, write: ResponseWriter, onError: ErrorHandler): Response = { | |
val res = handle(req, args) | |
(args, res match { | |
case (InitialArgs, r: BeginResponse) => write(r) | |
case (InitialArgs, _) => onError(new YouCantDoThisRightHereNowException()) | |
case (ContinuationArgs, r: EndResponse) => r | |
case (ContinuationArgs, r: Response) => { | |
write(r) | |
apply(h => handle(req, ContinuationArgs), write, onError) | |
} | |
} | |
} | |
def apply(req: Request, args: HandlerArgs) = { | |
(future { Executor((r, a) => handler(r, a), socket.send _) } onComplete (socket.send _) onException (throw _)).get | |
} | |
} | |
sealed trait Response { | |
type ContentType | |
def headers: Map[String, String] | |
def content: ContentType | |
def update(statusLine: String, headers: Map[String, String], content: ContentType): ResponsePrelude | |
} | |
sealed trait ResponsePrelude extends Response { | |
def statusLine: String | |
def update(statusLine: String, headers: Map[String, String], content: ContentType): ResponsePrelude | |
} | |
sealed trait ResponseCompletion { self: Response => | |
} | |
sealed trait ResponsePart extends Response { | |
def update(headers: Map[String, String], content: ContentType): ResponsePart | |
} | |
case class BeginResponse[T : Manifest](statusLine: String, headers: Map[String, String], content: T) extends ResponsePrelude { | |
type ContentType = T | |
def update(statusLine: String = this.statusLine, headers: Map[String, String] = headers, content: ContentType = content): ResponsePrelude = | |
copy(statusLine, headers, content) | |
} | |
case class ResponseChunk[T : Manifest](headers: Map[String, String], content: T) { | |
type ContentType = T | |
def update(headers: Map[String, String] = headers, content: ContentType = content): ResponsePrelude = | |
copy(headers, content) | |
} | |
case class EndResponse[T: Manifest](headers: Map[String, String], content: T) extends ResponseCompletion { | |
type ContentType = T | |
def update(headers: Map[String, String] = headers, content: ContentType = content): ResponsePrelude = | |
copy(headers, content) | |
} | |
case class DefaultResponse[T: Manifest](statusLine: String, headers: Map[String, String], content: T) extends ResponsePrelude with ResponseCompletion { | |
type ContentType = T | |
def update(statusLine: String = this.statusLine, headers: Map[String, String] = headers, content: ContentType = content): ResponsePrelude = | |
copy(statusLine, headers, content) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment