Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,9 @@ private[http] final class BodyPartParser(
emit(BodyPartStart(headers.toList, _ => HttpEntity.empty(contentType)))
val ix = lineStart + eolConfiguration.boundaryLength
if (eolConfiguration.isEndOfLine(input, ix))
parseHeaderLines(input, ix + eolConfiguration.eolLength, headers, headerCount, None)
// the boundary starts a new part, so its header state starts empty. Note this must stay a direct
// self-call: it is what keeps this method tail-recursive.
parseHeaderLines(input, ix + eolConfiguration.eolLength, ListBuffer[HttpHeader](), 0, None)
else if (doubleDash(input, ix)) setShouldTerminate()
else fail("Illegal multipart boundary in message content")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import scala.concurrent.duration._
import org.apache.pekko
import pekko.http.impl.util._
import pekko.http.scaladsl.model._
import pekko.http.scaladsl.settings.ParserSettings
import pekko.http.scaladsl.model.MediaTypes._
import pekko.http.scaladsl.model.headers._
import pekko.http.scaladsl.util.FastFuture._
Expand Down Expand Up @@ -62,6 +63,45 @@ trait MultipartUnmarshallersSpec extends PekkoSpecWithMaterializer {
|--XYZABC--""".stripMarginWithNewline(lineFeed)))).to[Multipart.General] should haveParts(
Multipart.General.BodyPart.Strict(HttpEntity.empty(ContentTypes.`text/xml(UTF-8)`), List(Age(12))))
}
"consecutive parts without header separation, each keeping its own headers" in {
Unmarshal(HttpEntity(
`multipart/mixed`.withBoundary("XYZABC"),
ByteString("""--XYZABC
|Age: 12
|--XYZABC
|Age: 13
|--XYZABC
|--XYZABC--""".stripMarginWithNewline(lineFeed)))).to[Multipart.General] should haveParts(
Multipart.General.BodyPart.Strict(HttpEntity.empty(ContentTypes.`text/plain(UTF-8)`), List(Age(12))),
Multipart.General.BodyPart.Strict(HttpEntity.empty(ContentTypes.`text/plain(UTF-8)`), List(Age(13))),
Multipart.General.BodyPart.Strict(HttpEntity.empty(ContentTypes.`text/plain(UTF-8)`)))
}
"a part without header separation not carrying its Content-Type into the next part" in {
Unmarshal(HttpEntity(
`multipart/mixed`.withBoundary("XYZABC"),
ByteString("""--XYZABC
|Content-type: text/xml; charset=UTF-8
|--XYZABC
|--XYZABC--""".stripMarginWithNewline(lineFeed)))).to[Multipart.General] should haveParts(
Multipart.General.BodyPart.Strict(HttpEntity.empty(ContentTypes.`text/xml(UTF-8)`)),
Multipart.General.BodyPart.Strict(HttpEntity.empty(ContentTypes.`text/plain(UTF-8)`)))
}
"parts without header separation counting headers per part, not across parts" in {
implicit val parserSettings: ParserSettings = ParserSettings(system).withMaxHeaderCount(2)
Unmarshal(HttpEntity(
`multipart/mixed`.withBoundary("XYZABC"),
ByteString("""--XYZABC
|Age: 12
|X-Foo: bar
|--XYZABC
|Age: 13
|X-Foo: baz
|--XYZABC--""".stripMarginWithNewline(lineFeed)))).to[Multipart.General] should haveParts(
Multipart.General.BodyPart.Strict(HttpEntity.empty(ContentTypes.`text/plain(UTF-8)`),
List(Age(12), RawHeader("X-Foo", "bar"))),
Multipart.General.BodyPart.Strict(HttpEntity.empty(ContentTypes.`text/plain(UTF-8)`),
List(Age(13), RawHeader("X-Foo", "baz"))))
}
"an implicitly typed part (without headers) (Strict)" in {
Unmarshal(HttpEntity(
`multipart/mixed`.withBoundary("XYZABC"),
Expand Down