diff --git a/akka-http-core/src/main/scala/akka/http/engine/parsing/HttpMessageParser.scala b/akka-http-core/src/main/scala/akka/http/engine/parsing/HttpMessageParser.scala index 7720e64847..ef3367ee8a 100644 --- a/akka-http-core/src/main/scala/akka/http/engine/parsing/HttpMessageParser.scala +++ b/akka-http-core/src/main/scala/akka/http/engine/parsing/HttpMessageParser.scala @@ -97,7 +97,7 @@ private[http] abstract class HttpMessageParser[Output >: MessageOutput <: Parser def badProtocol: Nothing - @tailrec final def parseHeaderLines(input: ByteString, lineStart: Int, headers: List[HttpHeader] = Nil, + @tailrec final def parseHeaderLines(input: ByteString, lineStart: Int, headers: ListBuffer[HttpHeader] = ListBuffer[HttpHeader](), headerCount: Int = 0, ch: Option[Connection] = None, clh: Option[`Content-Length`] = None, cth: Option[`Content-Type`] = None, teh: Option[`Transfer-Encoding`] = None, e100c: Boolean = false, @@ -117,7 +117,7 @@ private[http] abstract class HttpMessageParser[Output >: MessageOutput <: Parser case HttpHeaderParser.EmptyHeader ⇒ val close = HttpMessage.connectionCloseExpected(protocol, ch) setCompletionHandling(CompletionIsEntityStreamError) - parseEntity(headers, protocol, input, lineEnd, clh, cth, teh, e100c, hh, close) + parseEntity(headers.toList, protocol, input, lineEnd, clh, cth, teh, e100c, hh, close) case h: `Content-Length` ⇒ clh match { case None ⇒ parseHeaderLines(input, lineEnd, headers, headerCount + 1, ch, Some(h), cth, teh, e100c, hh) @@ -134,21 +134,21 @@ private[http] abstract class HttpMessageParser[Output >: MessageOutput <: Parser case Some(x) ⇒ parseHeaderLines(input, lineEnd, headers, headerCount, ch, clh, cth, Some(x append h.encodings), e100c, hh) } case h: Connection ⇒ ch match { - case None ⇒ parseHeaderLines(input, lineEnd, h :: headers, headerCount + 1, Some(h), clh, cth, teh, e100c, hh) + case None ⇒ parseHeaderLines(input, lineEnd, headers += h, headerCount + 1, Some(h), clh, cth, teh, e100c, hh) case Some(x) ⇒ parseHeaderLines(input, lineEnd, headers, headerCount, Some(x append h.tokens), clh, cth, teh, e100c, hh) } case h: Host ⇒ - if (!hh) parseHeaderLines(input, lineEnd, h :: headers, headerCount + 1, ch, clh, cth, teh, e100c, hh = true) + if (!hh) parseHeaderLines(input, lineEnd, headers += h, headerCount + 1, ch, clh, cth, teh, e100c, hh = true) else failMessageStart("HTTP message must not contain more than one Host header") - case h: Expect ⇒ parseHeaderLines(input, lineEnd, h :: headers, headerCount + 1, ch, clh, cth, teh, e100c = true, hh) + case h: Expect ⇒ parseHeaderLines(input, lineEnd, headers += h, headerCount + 1, ch, clh, cth, teh, e100c = true, hh) - case h ⇒ parseHeaderLines(input, lineEnd, h :: headers, headerCount + 1, ch, clh, cth, teh, e100c, hh) + case h ⇒ parseHeaderLines(input, lineEnd, headers += h, headerCount + 1, ch, clh, cth, teh, e100c, hh) } } else failMessageStart(s"HTTP message contains more than the configured limit of $maxHeaderCount headers") // work-around for compiler complaining about non-tail-recursion if we inline this method - def parseHeaderLinesAux(headers: List[HttpHeader], headerCount: Int, ch: Option[Connection], + def parseHeaderLinesAux(headers: ListBuffer[HttpHeader], headerCount: Int, ch: Option[Connection], clh: Option[`Content-Length`], cth: Option[`Content-Type`], teh: Option[`Transfer-Encoding`], e100c: Boolean, hh: Boolean)(input: ByteString, lineStart: Int): StateResult = parseHeaderLines(input, lineStart, headers, headerCount, ch, clh, cth, teh, e100c, hh) diff --git a/akka-http-core/src/test/scala/akka/http/ClientServerSpec.scala b/akka-http-core/src/test/scala/akka/http/ClientServerSpec.scala index 25be0cf585..1e971ef694 100644 --- a/akka-http-core/src/test/scala/akka/http/ClientServerSpec.scala +++ b/akka-http-core/src/test/scala/akka/http/ClientServerSpec.scala @@ -97,7 +97,7 @@ class ClientServerSpec extends WordSpec with Matchers with BeforeAndAfterAll { val serverInSub = serverIn.expectSubscription() serverInSub.request(1) - private val HttpRequest(POST, uri, List(`User-Agent`(_), Host(_, _), Accept(Vector(MediaRanges.`*/*`))), + private val HttpRequest(POST, uri, List(Accept(Seq(MediaRanges.`*/*`)), Host(_, _), `User-Agent`(_)), Chunked(`chunkedContentType`, chunkStream), HttpProtocols.`HTTP/1.1`) = serverIn.expectNext() uri shouldEqual Uri(s"http://$hostname:$port/chunked") Await.result(chunkStream.grouped(4).runWith(Sink.head), 100.millis) shouldEqual chunks @@ -107,7 +107,7 @@ class ClientServerSpec extends WordSpec with Matchers with BeforeAndAfterAll { val clientInSub = clientIn.expectSubscription() clientInSub.request(1) - val HttpResponse(StatusCodes.PartialContent, List(Date(_), Server(_), RawHeader("Age", "42")), + val HttpResponse(StatusCodes.PartialContent, List(RawHeader("Age", "42"), Server(_), Date(_)), Chunked(`chunkedContentType`, chunkStream2), HttpProtocols.`HTTP/1.1`) = clientIn.expectNext() Await.result(chunkStream2.grouped(1000).runWith(Sink.head), 100.millis) shouldEqual chunks } diff --git a/akka-http-core/src/test/scala/akka/http/engine/parsing/RequestParserSpec.scala b/akka-http-core/src/test/scala/akka/http/engine/parsing/RequestParserSpec.scala index b88ab93b67..377db41b8d 100644 --- a/akka-http-core/src/test/scala/akka/http/engine/parsing/RequestParserSpec.scala +++ b/akka-http-core/src/test/scala/akka/http/engine/parsing/RequestParserSpec.scala @@ -76,7 +76,7 @@ class RequestParserSpec extends FreeSpec with Matchers with BeforeAndAfterAll { |Content-length: 17 | |Shake your BOODY!""" should parseTo { - HttpRequest(POST, "/resource/yes", List(Connection("keep-alive"), `User-Agent`("curl/7.19.7 xyz")), + HttpRequest(POST, "/resource/yes", List(`User-Agent`("curl/7.19.7 xyz"), Connection("keep-alive")), "Shake your BOODY!", `HTTP/1.0`) } closeAfterResponseCompletion shouldEqual Seq(false) @@ -91,7 +91,7 @@ class RequestParserSpec extends FreeSpec with Matchers with BeforeAndAfterAll { |Shake your BOODY!GET / HTTP/1.0 | |""" should parseTo( - HttpRequest(POST, "/resource/yes", List(Connection("keep-alive"), `User-Agent`("curl/7.19.7 xyz")), + HttpRequest(POST, "/resource/yes", List(`User-Agent`("curl/7.19.7 xyz"), Connection("keep-alive")), "Shake your BOODY!".getBytes, `HTTP/1.0`), HttpRequest(protocol = `HTTP/1.0`)) closeAfterResponseCompletion shouldEqual Seq(false, true) @@ -107,8 +107,8 @@ class RequestParserSpec extends FreeSpec with Matchers with BeforeAndAfterAll { | fancy | |""" should parseTo { - HttpRequest(DELETE, "/abc", List(Connection("close", "fancy"), Accept(MediaRanges.`*/*`), - `User-Agent`("curl/7.19.7 abc xyz")), protocol = `HTTP/1.0`) + HttpRequest(DELETE, "/abc", List(`User-Agent`("curl/7.19.7 abc xyz"), Accept(MediaRanges.`*/*`), + Connection("close", "fancy")), protocol = `HTTP/1.0`) } closeAfterResponseCompletion shouldEqual Seq(true) } @@ -165,7 +165,7 @@ class RequestParserSpec extends FreeSpec with Matchers with BeforeAndAfterAll { |Host: ping | |""" - val baseRequest = HttpRequest(PATCH, "/data", List(Host("ping"), Connection("lalelu"))) + val baseRequest = HttpRequest(PATCH, "/data", List(Connection("lalelu"), Host("ping"))) "request start" in new Test { Seq(start, "rest") should generalMultiParseTo( @@ -217,7 +217,7 @@ class RequestParserSpec extends FreeSpec with Matchers with BeforeAndAfterAll { | |""") should generalMultiParseTo( Right(baseRequest.withEntity(Chunked(`application/pdf`, - source(LastChunk("nice=true", List(RawHeader("Bar", "xyz"), RawHeader("Foo", "pip apo")))))))) + source(LastChunk("nice=true", List(RawHeader("Foo", "pip apo"), RawHeader("Bar", "xyz")))))))) closeAfterResponseCompletion shouldEqual Seq(false) } @@ -276,7 +276,7 @@ class RequestParserSpec extends FreeSpec with Matchers with BeforeAndAfterAll { |Host: ping | |""" - val baseRequest = HttpRequest(PATCH, "/data", List(Host("ping"), Connection("lalelu")), + val baseRequest = HttpRequest(PATCH, "/data", List(Connection("lalelu"), Host("ping")), HttpEntity.Chunked(`application/octet-stream`, source())) "an illegal char after chunk size" in new Test { diff --git a/akka-http-core/src/test/scala/akka/http/engine/parsing/ResponseParserSpec.scala b/akka-http-core/src/test/scala/akka/http/engine/parsing/ResponseParserSpec.scala index 199f218267..305e36422f 100644 --- a/akka-http-core/src/test/scala/akka/http/engine/parsing/ResponseParserSpec.scala +++ b/akka-http-core/src/test/scala/akka/http/engine/parsing/ResponseParserSpec.scala @@ -105,7 +105,7 @@ class ResponseParserSpec extends FreeSpec with Matchers with BeforeAndAfterAll { |Content-Type: text/plain; charset=UTF-8 | |Sh""", "ake your BOODY!HTTP/1.") should generalMultiParseTo( - Right(HttpResponse(InternalServerError, List(Connection("close"), `User-Agent`("curl/7.19.7 xyz")), + Right(HttpResponse(InternalServerError, List(`User-Agent`("curl/7.19.7 xyz"), Connection("close")), "Shake your BOODY!"))) closeAfterResponseCompletion shouldEqual Seq(true) } @@ -130,7 +130,7 @@ class ResponseParserSpec extends FreeSpec with Matchers with BeforeAndAfterAll { |Server: spray-can | |""" - val baseResponse = HttpResponse(headers = List(Server("spray-can"), Connection("lalelu"))) + val baseResponse = HttpResponse(headers = List(Connection("lalelu"), Server("spray-can"))) "response start" in new Test { Seq(start, "rest") should generalMultiParseTo( @@ -181,7 +181,7 @@ class ResponseParserSpec extends FreeSpec with Matchers with BeforeAndAfterAll { | |HT""") should generalMultiParseTo( Right(baseResponse.withEntity(Chunked(`application/pdf`, - source(LastChunk("nice=true", List(RawHeader("Bar", "xyz"), RawHeader("Foo", "pip apo"))))))), + source(LastChunk("nice=true", List(RawHeader("Foo", "pip apo"), RawHeader("Bar", "xyz"))))))), Left(MessageStartError(400: StatusCode, ErrorInfo("Illegal HTTP message start")))) closeAfterResponseCompletion shouldEqual Seq(false) }