Skip to content
Browse files

Merge pull request #2276 from jkyamog/master

First 2 bytes of http headers getting dropped on some http client
  • Loading branch information...
2 parents 16bf844 + 85d4308 commit 09498080e7919dfce613e246d6a71b21d46487fc @huntc huntc committed Feb 25, 2014
View
4 framework/src/play/src/main/scala/play/api/mvc/ContentTypes.scala
@@ -632,9 +632,9 @@ trait BodyParsers {
val maxHeaderBuffer = Traversable.takeUpTo[Array[Byte]](4 * 1024) transform Iteratee.consume[Array[Byte]]()
val collectHeaders = maxHeaderBuffer.map { buffer =>
- val (headerBytes, rest) = Option(buffer.drop(2)).map(b => b.splitAt(b.indexOfSlice(CRLFCRLF))).get
+ val (headerBytes, rest) = Option(buffer).map(b => b.splitAt(b.indexOfSlice(CRLFCRLF))).get
- val headerString = new String(headerBytes, "utf-8")
+ val headerString = new String(headerBytes, "utf-8").trim
val headers = headerString.lines.map { header =>
val key :: value = header.trim.split(":").toList
(key.trim.toLowerCase, value.mkString.trim)
View
47 framework/src/play/src/test/scala/play/api/mvc/ContentTypesSpec.scala
@@ -5,6 +5,10 @@ package play.api.mvc
import org.specs2.mutable.Specification
import scalax.io.Resource
+import scala.concurrent.Await
+import scala.concurrent.Future
+import scala.concurrent.duration._
+import play.api.libs.iteratee.Enumerator
object ContentTypesSpec extends Specification {
@@ -93,5 +97,48 @@ object ContentTypesSpec extends Specification {
Resource.fromFile(file).string must_== "hello world"
}
}
+
+ "Multipart parser" should {
+
+ "get the file parts" in {
+ testMultiPart("-----------------------------117723558510316372842092349957\r\nContent-Disposition: form-data; name=\"picture\"; filename=\"README\"\r\nContent-Type: application/octet-stream\r\n\r\nThis is your new Play application\r\n=====================================\r\nThis file will be packaged with your application, when using `play dist`.\r\n-----------------------------117723558510316372842092349957--\r\n")
+ }
+
+ "get the file parts with boundary that has no CRLF at start" in {
+ testMultiPart("-----------------------------117723558510316372842092349957Content-Disposition: form-data; name=\"picture\"; filename=\"README\"\r\nContent-Type: application/octet-stream\r\n\r\nThis is your new Play application\r\n=====================================\r\nThis file will be packaged with your application, when using `play dist`.\r\n-----------------------------117723558510316372842092349957--\r\n")
+ }
+
+ def testMultiPart(testMultipartBody: String) = {
+
+ def await[T](f: Future[T]) = Await.result(f, Duration("5 seconds"))
+ case class TestRequestHeader(headers: Headers, method: String = "GET", uri: String = "/", path: String = "", remoteAddress: String = "127.0.0.1", version: String = "HTTP/1.1", id: Long = 1, tags: Map[String, String] = Map.empty[String, String], queryString: Map[String, Seq[String]] = Map(), secure: Boolean = false) extends RequestHeader
+ val multipartFormDataParser = BodyParsers.parse.multipartFormData
+
+ val rh = TestRequestHeader(headers = new Headers {
+ val data = Seq(play.api.http.HeaderNames.CONTENT_TYPE -> Seq("multipart/form-data; boundary=---------------------------117723558510316372842092349957"), play.api.http.HeaderNames.CONTENT_LENGTH -> Seq("382"))
+ })
+
+ val body = Enumerator(testMultipartBody.getBytes)
+ val parsedResult = await(body run multipartFormDataParser(rh))
+
+ parsedResult.isRight must beTrue
+
+ parsedResult match {
+ case Right(multipartFormData) =>
+ multipartFormData.badParts.isEmpty must beTrue
+ multipartFormData.missingFileParts.isEmpty must beTrue
+ multipartFormData.dataParts.isEmpty must beTrue
+
+ multipartFormData.files.size must_== 1
+ val filePart = multipartFormData.files.head
+ filePart.filename must_== "README"
+ filePart.contentType must beSome("application/octet-stream")
+ filePart.key must_== "picture"
+ success
+ case Left(_) =>
+ failure("must not get a Left result")
+ }
+ }
+ }
}

0 comments on commit 0949808

Please sign in to comment.
Something went wrong with that request. Please try again.