=str #19293 fix issues in Sink.seq + minor doc fixes + use Sink.seq and limit in tests where appropriate
* Sink.seq (Scala DSL) now returns immutable.Seq rather than Seq * Sink.seq will not silently truncate when incoming elements is > Int.MAX_VALUE * minor doc fixes * replacing various grouped(n) / Sink.head with limit(n) / Sink.seq in various tests * fix inconsistent indentation in RequestParserSpec
This commit is contained in:
parent
f042204d8b
commit
21381d5710
46 changed files with 330 additions and 217 deletions
|
|
@ -252,7 +252,7 @@ class RequestParserSpec extends FreeSpec with Matchers with BeforeAndAfterAll {
|
|||
val parser = newParser
|
||||
val result = multiParse(newParser)(Seq(prep(start + manyChunks)))
|
||||
val HttpEntity.Chunked(_, chunks) = result.head.right.get.req.entity
|
||||
val strictChunks = chunks.grouped(100000).runWith(Sink.head).awaitResult(awaitAtMost)
|
||||
val strictChunks = chunks.limit(100000).runWith(Sink.seq).awaitResult(awaitAtMost)
|
||||
strictChunks.size shouldEqual numChunks
|
||||
}
|
||||
}
|
||||
|
|
@ -322,7 +322,7 @@ class RequestParserSpec extends FreeSpec with Matchers with BeforeAndAfterAll {
|
|||
"too-large chunk size" in new Test {
|
||||
Seq(start,
|
||||
"""1a2b3c4d5e
|
||||
|""") should generalMultiParseTo(Right(baseRequest),
|
||||
|""") should generalMultiParseTo(Right(baseRequest),
|
||||
Left(EntityStreamError(ErrorInfo("HTTP chunk size exceeds the configured limit of 1048576 bytes"))))
|
||||
closeAfterResponseCompletion shouldEqual Seq(false)
|
||||
}
|
||||
|
|
@ -360,10 +360,10 @@ class RequestParserSpec extends FreeSpec with Matchers with BeforeAndAfterAll {
|
|||
|
||||
"two Content-Length headers" in new Test {
|
||||
"""GET / HTTP/1.1
|
||||
|Content-Length: 3
|
||||
|Content-Length: 4
|
||||
|
|
||||
|foo""" should parseToError(BadRequest,
|
||||
|Content-Length: 3
|
||||
|Content-Length: 4
|
||||
|
|
||||
|foo""" should parseToError(BadRequest,
|
||||
ErrorInfo("HTTP message must not contain more than one Content-Length header"))
|
||||
}
|
||||
|
||||
|
|
@ -374,63 +374,63 @@ class RequestParserSpec extends FreeSpec with Matchers with BeforeAndAfterAll {
|
|||
|
||||
"HTTP version 1.2" in new Test {
|
||||
"""GET / HTTP/1.2
|
||||
|""" should parseToError(HTTPVersionNotSupported,
|
||||
|""" should parseToError(HTTPVersionNotSupported,
|
||||
ErrorInfo("The server does not support the HTTP protocol version used in the request."))
|
||||
}
|
||||
|
||||
"with an illegal char in a header name" in new Test {
|
||||
"""GET / HTTP/1.1
|
||||
|User@Agent: curl/7.19.7""" should parseToError(BadRequest, ErrorInfo("Illegal character '@' in header name"))
|
||||
|User@Agent: curl/7.19.7""" should parseToError(BadRequest, ErrorInfo("Illegal character '@' in header name"))
|
||||
}
|
||||
|
||||
"with a too-long header name" in new Test {
|
||||
"""|GET / HTTP/1.1
|
||||
|UserxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxAgent: curl/7.19.7""" should parseToError(
|
||||
|UserxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxAgent: curl/7.19.7""" should parseToError(
|
||||
BadRequest, ErrorInfo("HTTP header name exceeds the configured limit of 64 characters"))
|
||||
}
|
||||
|
||||
"with a too-long header-value" in new Test {
|
||||
"""|GET / HTTP/1.1
|
||||
|Fancy: 123456789012345678901234567890123""" should parseToError(BadRequest,
|
||||
|Fancy: 123456789012345678901234567890123""" should parseToError(BadRequest,
|
||||
ErrorInfo("HTTP header value exceeds the configured limit of 32 characters"))
|
||||
}
|
||||
|
||||
"with an invalid Content-Length header value" in new Test {
|
||||
"""GET / HTTP/1.0
|
||||
|Content-Length: 1.5
|
||||
|
|
||||
|abc""" should parseToError(BadRequest, ErrorInfo("Illegal `Content-Length` header value"))
|
||||
|Content-Length: 1.5
|
||||
|
|
||||
|abc""" should parseToError(BadRequest, ErrorInfo("Illegal `Content-Length` header value"))
|
||||
}
|
||||
|
||||
"with Content-Length > Long.MaxSize" in new Test {
|
||||
// content-length = (Long.MaxValue + 1) * 10, which is 0 when calculated overflow
|
||||
"""PUT /resource/yes HTTP/1.1
|
||||
|Content-length: 92233720368547758080
|
||||
|Host: x
|
||||
|
|
||||
|""" should parseToError(400: StatusCode, ErrorInfo("`Content-Length` header value must not exceed 63-bit integer range"))
|
||||
|Content-length: 92233720368547758080
|
||||
|Host: x
|
||||
|
|
||||
|""" should parseToError(400: StatusCode, ErrorInfo("`Content-Length` header value must not exceed 63-bit integer range"))
|
||||
}
|
||||
|
||||
"with an illegal entity using CONNECT" in new Test {
|
||||
"""CONNECT /resource/yes HTTP/1.1
|
||||
|Transfer-Encoding: chunked
|
||||
|Host: x
|
||||
|
|
||||
|""" should parseToError(422: StatusCode, ErrorInfo("CONNECT requests must not have an entity"))
|
||||
|Transfer-Encoding: chunked
|
||||
|Host: x
|
||||
|
|
||||
|""" should parseToError(422: StatusCode, ErrorInfo("CONNECT requests must not have an entity"))
|
||||
}
|
||||
"with an illegal entity using HEAD" 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"))
|
||||
|Content-length: 3
|
||||
|Host: x
|
||||
|
|
||||
|foo""" should parseToError(422: StatusCode, ErrorInfo("HEAD requests must not have an entity"))
|
||||
}
|
||||
"with an illegal entity using TRACE" in new Test {
|
||||
"""TRACE /resource/yes HTTP/1.1
|
||||
|Transfer-Encoding: chunked
|
||||
|Host: x
|
||||
|
|
||||
|""" should parseToError(422: StatusCode, ErrorInfo("TRACE requests must not have an entity"))
|
||||
|Transfer-Encoding: chunked
|
||||
|Host: x
|
||||
|
|
||||
|""" should parseToError(422: StatusCode, ErrorInfo("TRACE requests must not have an entity"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -504,7 +504,7 @@ class RequestParserSpec extends FreeSpec with Matchers with BeforeAndAfterAll {
|
|||
}
|
||||
}
|
||||
.map(strictEqualify)
|
||||
.grouped(100000).runWith(Sink.head)
|
||||
.limit(100000).runWith(Sink.seq)
|
||||
.awaitResult(awaitAtMost)
|
||||
|
||||
protected def parserSettings: ParserSettings = ParserSettings(system)
|
||||
|
|
@ -517,7 +517,7 @@ class RequestParserSpec extends FreeSpec with Matchers with BeforeAndAfterAll {
|
|||
}
|
||||
|
||||
private def compactEntityChunks(data: Source[ChunkStreamPart, Any]): Future[Seq[ChunkStreamPart]] =
|
||||
data.grouped(100000).runWith(Sink.head)
|
||||
data.limit(100000).runWith(Sink.seq)
|
||||
.fast.recover { case _: NoSuchElementException ⇒ Nil }
|
||||
|
||||
def prep(response: String) = response.stripMarginWithNewline("\r\n")
|
||||
|
|
|
|||
|
|
@ -306,7 +306,7 @@ class ResponseParserSpec extends FreeSpec with Matchers with BeforeAndAfterAll {
|
|||
}.concatSubstreams
|
||||
|
||||
def collectBlocking[T](source: Source[T, Any]): Seq[T] =
|
||||
Await.result(source.grouped(100000).runWith(Sink.head), 500.millis)
|
||||
Await.result(source.limit(100000).runWith(Sink.seq), 500.millis)
|
||||
|
||||
protected def parserSettings: ParserSettings = ParserSettings(system)
|
||||
|
||||
|
|
@ -323,7 +323,7 @@ class ResponseParserSpec extends FreeSpec with Matchers with BeforeAndAfterAll {
|
|||
}
|
||||
|
||||
private def compactEntityChunks(data: Source[ChunkStreamPart, Any]): Future[Source[ChunkStreamPart, Any]] =
|
||||
data.grouped(100000).runWith(Sink.head)
|
||||
data.limit(100000).runWith(Sink.seq)
|
||||
.fast.map(source(_: _*))
|
||||
.fast.recover { case _: NoSuchElementException ⇒ source() }
|
||||
|
||||
|
|
|
|||
|
|
@ -325,7 +325,7 @@ class RequestRendererSpec extends FreeSpec with Matchers with BeforeAndAfterAll
|
|||
def renderTo(expected: String): Matcher[HttpRequest] =
|
||||
equal(expected.stripMarginWithNewline("\r\n")).matcher[String] compose { request ⇒
|
||||
val byteStringSource = renderToSource(RequestRenderingContext(request, Host(serverAddress)))
|
||||
val future = byteStringSource.grouped(1000).runWith(Sink.head).map(_.reduceLeft(_ ++ _).utf8String)
|
||||
val future = byteStringSource.limit(1000).runWith(Sink.seq).map(_.reduceLeft(_ ++ _).utf8String)
|
||||
Await.result(future, 250.millis)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -394,7 +394,7 @@ class ClientServerSpec extends WordSpec with Matchers with BeforeAndAfterAll wit
|
|||
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(5).runWith(Sink.head), 100.millis) shouldEqual chunks
|
||||
Await.result(chunkStream.limit(5).runWith(Sink.seq), 100.millis) shouldEqual chunks
|
||||
|
||||
val serverOutSub = serverOut.expectSubscription()
|
||||
serverOutSub.expectRequest()
|
||||
|
|
@ -404,7 +404,7 @@ class ClientServerSpec extends WordSpec with Matchers with BeforeAndAfterAll wit
|
|||
clientInSub.request(1)
|
||||
val HttpResponse(StatusCodes.PartialContent, List(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
|
||||
Await.result(chunkStream2.limit(1000).runWith(Sink.seq), 100.millis) shouldEqual chunks
|
||||
|
||||
clientOutSub.sendComplete()
|
||||
serverInSub.request(1)
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ class HttpEntitySpec extends FreeSpec with MustMatchers with BeforeAndAfterAll {
|
|||
|
||||
def collectBytesTo(bytes: ByteString*): Matcher[HttpEntity] =
|
||||
equal(bytes.toVector).matcher[Seq[ByteString]].compose { entity ⇒
|
||||
val future = entity.dataBytes.grouped(1000).runWith(Sink.head)
|
||||
val future = entity.dataBytes.limit(1000).runWith(Sink.seq)
|
||||
Await.result(future, 250.millis)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue