+htc #20272 HttpMessageParser swallows IllegalHeaderException (#20783)

Catch clause in HttpMessageParser.parseBytes will intercept IllegalHeaderException being thrown and translate them into proper errors.
This commit is contained in:
Patryk Jażdżewski 2016-06-21 16:30:25 +02:00 committed by Konrad Malawski
parent 277e7124e0
commit 7259fcc534
3 changed files with 60 additions and 0 deletions

View file

@ -84,6 +84,8 @@ private[http] abstract class HttpMessageParser[Output >: MessageOutput <: Parser
case NotEnoughDataException
// we are missing a try/catch{continue} wrapper somewhere
throw new IllegalStateException("unexpected NotEnoughDataException", NotEnoughDataException)
case IllegalHeaderException(error)
failMessageStart(StatusCodes.BadRequest, error)
}) match {
case Trampoline(x) run(x)
case x x

View file

@ -175,6 +175,28 @@ class RequestParserSpec extends FreeSpec with Matchers with BeforeAndAfterAll {
|""" should parseTo(HttpRequest(GET, Uri("http://x//foo").toHttpRequestTargetOriginForm, protocol = `HTTP/1.0`))
closeAfterResponseCompletion shouldEqual Seq(true)
}
"with additional fields in Strict-Transport-Security header" in new Test {
"""GET /hsts HTTP/1.1
|Host: x
|Strict-Transport-Security: max-age=1; preload; dummy
|
|""" should parseTo(HttpRequest(
GET,
"/hsts",
headers = List(Host("x"), `Strict-Transport-Security`(1, None)),
protocol = `HTTP/1.1`))
"""GET /hsts HTTP/1.1
|Host: x
|Strict-Transport-Security: max-age=1; dummy; preload
|
|""" should parseTo(HttpRequest(
GET,
"/hsts",
headers = List(Host("x"), `Strict-Transport-Security`(1, None)),
protocol = `HTTP/1.1`))
}
}
"properly parse a chunked request" - {
@ -453,6 +475,36 @@ class RequestParserSpec extends FreeSpec with Matchers with BeforeAndAfterAll {
|
|""" should parseToError(422: StatusCode, ErrorInfo("TRACE requests must not have an entity"))
}
"with additional fields in headers" in new Test {
"""GET / HTTP/1.1
|Host: x; dummy
|
|""" should parseToError(
BadRequest,
ErrorInfo("Illegal 'host' header: Invalid input ' ', expected 'EOI', ':', UPPER_ALPHA, lower-reg-name-char or pct-encoded (line 1, column 3)", "x; dummy\n ^"))
"""GET / HTTP/1.1
|Content-length: 3; dummy
|
|""" should parseToError(
BadRequest,
ErrorInfo("Illegal `Content-Length` header value"))
"""GET / HTTP/1.1
|Connection:keep-alive; dummy
|
|""" should parseToError(
BadRequest,
ErrorInfo("Illegal 'connection' header: Invalid input ';', expected tchar, OWS, listSep or 'EOI' (line 1, column 11)", "keep-alive; dummy\n ^"))
"""GET / HTTP/1.1
|Transfer-Encoding: chunked; dummy
|
|""" should parseToError(
BadRequest,
ErrorInfo("Illegal 'transfer-encoding' header: Invalid input ';', expected OWS, listSep or 'EOI' (line 1, column 8)", "chunked; dummy\n ^"))
}
}
}

View file

@ -68,6 +68,12 @@ class HeaderSpec extends FreeSpec with Matchers {
headers.`Strict-Transport-Security`.parseFromValueString("max-age=30; includeSubDomains") shouldEqual Right(headers.`Strict-Transport-Security`(30, true))
headers.`Strict-Transport-Security`.parseFromValueString("max-age=30; includeSubDomains; preload") shouldEqual Right(headers.`Strict-Transport-Security`(30, true))
}
"successful parse run with additional values" in {
headers.`Strict-Transport-Security`.parseFromValueString("max-age=30; includeSubDomains; preload; dummy") shouldEqual
Right(headers.`Strict-Transport-Security`(30, true))
headers.`Strict-Transport-Security`.parseFromValueString("max-age=30; includeSubDomains; dummy; preload") shouldEqual
Right(headers.`Strict-Transport-Security`(30, true))
}
"failing parse run" in {
val Left(List(ErrorInfo(summary, detail))) = `Strict-Transport-Security`.parseFromValueString("max-age=30; includeSubDomains; preload;")
summary shouldEqual "Illegal HTTP header 'Strict-Transport-Security': Invalid input 'EOI', expected OWS or token0 (line 1, column 40)"