Skip to content

Instantly share code, notes, and snippets.

@JosephMoniz
Last active August 29, 2015 13:55
Show Gist options
  • Save JosephMoniz/8701085 to your computer and use it in GitHub Desktop.
Save JosephMoniz/8701085 to your computer and use it in GitHub Desktop.
Scala combinatorial http parser
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