Last active
August 29, 2015 13:55
-
-
Save PipelineBaron/8701085 to your computer and use it in GitHub Desktop.
Scala combinatorial http parser
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
| package com.blackboxsociety.http | |
| import scala.util.parsing.combinator._ | |
| sealed trait HttpMethod | |
| case object HttpGet extends HttpMethod | |
| case object HttpHead extends HttpMethod | |
| case object HttpPost extends HttpMethod | |
| case object HttpPut extends HttpMethod | |
| case object HttpDelete extends HttpMethod | |
| case object HttpTrace extends HttpMethod | |
| case object HttpOptions extends HttpMethod | |
| case object HttpConnect extends HttpMethod | |
| case object HttpPatch extends HttpMethod | |
| case class HttpResource(path: String) | |
| sealed trait HttpVersion | |
| case object HttpVersionOneDotZero extends HttpVersion | |
| case object HttpVersionOneDotOne extends HttpVersion | |
| case class HttpHeader(key: String, value: String) | |
| case class HttpRequest(method: HttpMethod, | |
| resource: HttpResource, | |
| version: HttpVersion, | |
| headers: List[HttpHeader]) | |
| object HttpParser extends RegexParsers { | |
| def skipWhiteSpace = false | |
| def spaces = """ +""".r | |
| def nonSpaces = """[^ ]+""".r | |
| def lineEnd = """\r\n""" | |
| def nonEndings = """[^\r\n]+""".r | |
| def httpGet: Parser[HttpMethod] = "GET" ^^ { _ => | |
| HttpGet | |
| } | |
| def httpHead: Parser[HttpMethod] = "HEAD" ^^ { _ => | |
| HttpHead | |
| } | |
| def httpPost: Parser[HttpMethod] = "POST" ^^ { _ => | |
| HttpPost | |
| } | |
| def httpPut: Parser[HttpMethod] = "PUT" ^^ { _ => | |
| HttpPut | |
| } | |
| def httpDelete: Parser[HttpMethod] = "DELETE" ^^ { _ => | |
| HttpDelete | |
| } | |
| def httpTrace: Parser[HttpMethod] = "TRACE" ^^ { _ => | |
| HttpTrace | |
| } | |
| def httpOptions: Parser[HttpMethod] = "OPTIONS" ^^ { _ => | |
| HttpOptions | |
| } | |
| def httpConnect: Parser[HttpMethod] = "CONNECT" ^^ { _ => | |
| HttpConnect | |
| } | |
| def httpPatch: Parser[HttpMethod] = "PATCH" ^^ { _ => | |
| HttpPatch | |
| } | |
| def httpResource: Parser[HttpResource] = nonSpaces ^^ { n => | |
| HttpResource(n) | |
| } | |
| def httpMethod: Parser[HttpMethod] = httpGet | | |
| httpHead | | |
| httpPost | | |
| httpPut | | |
| httpDelete | | |
| httpTrace | | |
| httpOptions | | |
| httpConnect | | |
| httpPatch | |
| def httpVersionLegacy: Parser[HttpVersion] = "HTTP/1.0" ^^ { _ => | |
| HttpVersionOneDotZero | |
| } | |
| def httpVersionModern: Parser[HttpVersion] = "HTTP/1.1" ^^ { _ => | |
| HttpVersionOneDotOne | |
| } | |
| def httpVersion: Parser[HttpVersion] = httpVersionLegacy | httpVersionModern | |
| def httpHeader: Parser[HttpHeader] = "[^:]+".r ~ ":" ~ spaces ~ nonEndings ~ lineEnd ^^ { | |
| case (key ~ _ ~ _ ~ value ~ _) => HttpHeader(key, value) | |
| } | |
| def apply: Parser[HttpRequest] = httpMethod ~ | |
| " " ~ | |
| httpResource ~ | |
| " " ~ | |
| httpVersion ~ | |
| lineEnd ~ | |
| rep(httpHeader) ~ | |
| repN(2, lineEnd) ^^ | |
| { | |
| case (method ~ _ ~ resource ~ _ ~ version ~ _ ~ headers ~ _) => HttpRequest( | |
| method, | |
| resource, | |
| version, | |
| headers | |
| ) | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment