=htc #15670 add convenience BodyPart extractors

This commit is contained in:
Johannes Rudolph 2014-08-21 12:03:19 +02:00
parent f4bc1704d3
commit 8c85cc41d3
3 changed files with 92 additions and 7 deletions

View file

@ -4,10 +4,6 @@
package akka.http.model.japi;
import akka.util.ByteString;
import java.io.File;
/**
* A marker type that denotes HttpEntity subtypes that can be used in Http requests.
*/

View file

@ -85,10 +85,10 @@ object MultipartFormData {
}
}
final case class FormFile(name: Option[String], entity: HttpEntity.Default)
final case class FormFile(name: Option[String], entity: HttpEntity)
object FormFile {
def apply(name: String, entity: HttpEntity.Default): FormFile = apply(Some(name), entity)
def apply(name: String, entity: HttpEntity): FormFile = apply(Some(name), entity)
}
/**
@ -129,4 +129,39 @@ object BodyPart {
def apply(entity: HttpEntity, fieldName: String): BodyPart = apply(entity, fieldName, Map.empty[String, String])
def apply(entity: HttpEntity, fieldName: String, params: Map[String, String]): BodyPart =
BodyPart(entity, immutable.Seq(`Content-Disposition`(ContentDispositionTypes.`form-data`, params.updated("name", fieldName))))
}
}
/**
* A convenience extractor that allows to match on a BodyPart including its name if the body-part
* is used as part of form-data. If the part has no name the extractor won't match.
*
* Example:
*
* {{{
* (formData: StrictMultipartFormData).fields collect {
* case NamedBodyPart("address", data, headers) => data
* }
* }}}
*/
object NamedBodyPart {
def unapply(part: BodyPart): Option[(String, HttpEntity, immutable.Seq[HttpHeader])] =
part.name.map(name (name, part.entity, part.headers))
}
/**
* A convenience extractor that allows to match on a BodyPart including its name and filename
* if the body-part is used as part of form-data. If the part has no name an empty string will be
* extracted, instead. If the part has no filename the extractor won't match.
*
* Example:
*
* {{{
* (formData: StrictMultipartFormData).fields collect {
* case FileBodyPart("file", filename, data, headers) => filename -> data
* }
* }}}
*/
object FileBodyPart {
def unapply(part: BodyPart): Option[(String, String, HttpEntity, immutable.Seq[HttpHeader])] =
part.filename.map(filename (part.name.getOrElse(""), filename, part.entity, part.headers))
}

View file

@ -0,0 +1,54 @@
/*
* Copyright (C) 2009-2014 Typesafe Inc. <http://www.typesafe.com>
*/
package akka.http.model
import akka.http.model.headers.{ ContentDispositionTypes, `Content-Disposition` }
import akka.util.ByteString
import org.scalatest.{ Inside, Matchers, WordSpec }
class MultipartContentSpec extends WordSpec with Matchers with Inside {
"BodyPart" should {
val data = HttpEntity(ByteString("data"))
"be matched with NamedBodyPart extractor if it has a name" in {
val part = BodyPart(data, "name")
inside(part) {
case NamedBodyPart("name", entity, _) entity should equal(data)
}
}
"not be matched with NamedBodyPart extractor if it has no name" in {
val part = BodyPart(data)
inside(part) {
case NamedBodyPart(name, entity, _) fail(s"Shouldn't match but did match with name '$name'")
case _
}
}
"be matched with FileBodyPart extractor if it contains a file" in {
val part = BodyPart(FormFile("data.txt", data), "name")
inside(part) {
case FileBodyPart("name", "data.txt", entity, _) entity should equal(data)
}
}
"be matched with FileBodyPart extractor if it contains a file but no name" in {
val part = BodyPart(data, `Content-Disposition`(ContentDispositionTypes.`form-data`, Map("filename" -> "data.txt")) :: Nil)
inside(part) {
case FileBodyPart("", "data.txt", entity, _) entity should equal(data)
}
}
"not be matched with NamedBodyPart extractor if it doesn't contains a file" in {
val part = BodyPart(data)
inside(part) {
case FileBodyPart(name, filename, entity, _) fail(s"Shouldn't match but did match with name '$name' and filename '$filename'")
case _
}
}
}
}