Catch clause in HttpMessageParser.parseBytes will intercept IllegalHeaderException being thrown and translate them into proper errors.
This commit is contained in:
parent
277e7124e0
commit
7259fcc534
3 changed files with 60 additions and 0 deletions
|
|
@ -84,6 +84,8 @@ private[http] abstract class HttpMessageParser[Output >: MessageOutput <: Parser
|
||||||
case NotEnoughDataException ⇒
|
case NotEnoughDataException ⇒
|
||||||
// we are missing a try/catch{continue} wrapper somewhere
|
// we are missing a try/catch{continue} wrapper somewhere
|
||||||
throw new IllegalStateException("unexpected NotEnoughDataException", NotEnoughDataException)
|
throw new IllegalStateException("unexpected NotEnoughDataException", NotEnoughDataException)
|
||||||
|
case IllegalHeaderException(error) ⇒
|
||||||
|
failMessageStart(StatusCodes.BadRequest, error)
|
||||||
}) match {
|
}) match {
|
||||||
case Trampoline(x) ⇒ run(x)
|
case Trampoline(x) ⇒ run(x)
|
||||||
case x ⇒ x
|
case x ⇒ x
|
||||||
|
|
|
||||||
|
|
@ -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`))
|
|""" should parseTo(HttpRequest(GET, Uri("http://x//foo").toHttpRequestTargetOriginForm, protocol = `HTTP/1.0`))
|
||||||
closeAfterResponseCompletion shouldEqual Seq(true)
|
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" - {
|
"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"))
|
|""" 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 ^"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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") 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))
|
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 {
|
"failing parse run" in {
|
||||||
val Left(List(ErrorInfo(summary, detail))) = `Strict-Transport-Security`.parseFromValueString("max-age=30; includeSubDomains; preload;")
|
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)"
|
summary shouldEqual "Illegal HTTP header 'Strict-Transport-Security': Invalid input 'EOI', expected OWS or token0 (line 1, column 40)"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue