diff --git a/akka-http-core/src/main/scala/akka/http/impl/engine/parsing/HttpRequestParser.scala b/akka-http-core/src/main/scala/akka/http/impl/engine/parsing/HttpRequestParser.scala index 7b0c3c7abb..7afccab3cb 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/engine/parsing/HttpRequestParser.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/engine/parsing/HttpRequestParser.scala @@ -167,6 +167,8 @@ private[http] class HttpRequestParser(_settings: ParserSettings, emitRequestStart(emptyEntity(cth)) setCompletionHandling(HttpMessageParser.CompletionOk) startNewMessage(input, bodyStart) + } else if (!method.isEntityAccepted) { + failMessageStart(UnprocessableEntity, s"${method.name} requests must not have an entity") } else if (contentLength <= input.size - bodyStart) { val cl = contentLength.toInt emitRequestStart(strictEntity(cth, input, bodyStart, cl)) @@ -177,6 +179,9 @@ private[http] class HttpRequestParser(_settings: ParserSettings, parseFixedLengthBody(contentLength, closeAfterResponseCompletion)(input, bodyStart) } + case Some(_) if !method.isEntityAccepted ⇒ + failMessageStart(UnprocessableEntity, s"${method.name} requests must not have an entity") + case Some(te) ⇒ val completedHeaders = addTransferEncodingWithChunkedPeeled(headers, te) if (te.isChunked) { diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/parsing/RequestParserSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/parsing/RequestParserSpec.scala index 70bdd30d5f..f78f373ba9 100644 --- a/akka-http-core/src/test/scala/akka/http/impl/engine/parsing/RequestParserSpec.scala +++ b/akka-http-core/src/test/scala/akka/http/impl/engine/parsing/RequestParserSpec.scala @@ -138,11 +138,11 @@ class RequestParserSpec extends FreeSpec with Matchers with BeforeAndAfterAll { } "with a funky `Transfer-Encoding` header" in new Test { - """GET / HTTP/1.1 + """PUT / HTTP/1.1 |Transfer-Encoding: foo, chunked, bar |Host: x | - |""" should parseTo(HttpRequest(GET, "/", List(`Transfer-Encoding`(TransferEncodings.Extension("foo"), + |""" should parseTo(HttpRequest(PUT, "/", List(`Transfer-Encoding`(TransferEncodings.Extension("foo"), TransferEncodings.chunked, TransferEncodings.Extension("bar")), Host("x")))) closeAfterResponseCompletion shouldEqual Seq(false) } @@ -399,6 +399,19 @@ class RequestParserSpec extends FreeSpec with Matchers with BeforeAndAfterAll { | |""" should parseToError(400: StatusCode, ErrorInfo("`Content-Length` header value must not exceed 63-bit integer range")) } + + "with an illegal entity" in new Test { + """HEAD /resource/yes HTTP/1.1 + |Content-length: 3 + |Host: x + | + |foo""" should parseToError(422: StatusCode, ErrorInfo("HEAD requests must not have an entity")) + """DELETE /resource/yes HTTP/1.1 + |Transfer-Encoding: chunked + |Host: x + | + |""" should parseToError(422: StatusCode, ErrorInfo("DELETE requests must not have an entity")) + } } } }