diff options
author | adamw <adam@warski.org> | 2017-08-29 12:59:00 +0200 |
---|---|---|
committer | adamw <adam@warski.org> | 2017-08-29 12:59:00 +0200 |
commit | 75a010d974aac96e8c96d34e38590c219cdca900 (patch) | |
tree | 4b42f6c996b4ac5c69e5a57a63c9d4fe7fa2dc79 /core/src/main | |
parent | d30fb75be34d1bbf7a13a43ca4a4ebbb633ab74d (diff) | |
download | sttp-75a010d974aac96e8c96d34e38590c219cdca900.tar.gz sttp-75a010d974aac96e8c96d34e38590c219cdca900.tar.bz2 sttp-75a010d974aac96e8c96d34e38590c219cdca900.zip |
Multipart support in Akka handler
Diffstat (limited to 'core/src/main')
-rw-r--r-- | core/src/main/scala/com/softwaremill/sttp/Multipart.scala (renamed from core/src/main/scala/com/softwaremill/sttp/MultiPart.scala) | 12 | ||||
-rw-r--r-- | core/src/main/scala/com/softwaremill/sttp/RequestT.scala | 19 | ||||
-rw-r--r-- | core/src/main/scala/com/softwaremill/sttp/model/RequestBody.scala | 21 | ||||
-rw-r--r-- | core/src/main/scala/com/softwaremill/sttp/package.scala | 87 |
4 files changed, 108 insertions, 31 deletions
diff --git a/core/src/main/scala/com/softwaremill/sttp/MultiPart.scala b/core/src/main/scala/com/softwaremill/sttp/Multipart.scala index eb7badb..c54c615 100644 --- a/core/src/main/scala/com/softwaremill/sttp/MultiPart.scala +++ b/core/src/main/scala/com/softwaremill/sttp/Multipart.scala @@ -3,17 +3,17 @@ package com.softwaremill.sttp import com.softwaremill.sttp.model.BasicRequestBody /** - * Use the factory methods `multiPart` to conveniently create instances of + * Use the factory methods `multipart` to conveniently create instances of * this class. A part can be then further customised using `fileName`, * `contentType` and `header` methods. */ -case class MultiPart(name: String, - data: BasicRequestBody, +case class Multipart(name: String, + body: BasicRequestBody, fileName: Option[String] = None, contentType: Option[String] = None, additionalHeaders: Map[String, String] = Map()) { - def fileName(v: String): MultiPart = copy(fileName = Some(v)) - def contentType(v: String): MultiPart = copy(contentType = Some(v)) - def header(k: String, v: String): MultiPart = + def fileName(v: String): Multipart = copy(fileName = Some(v)) + def contentType(v: String): Multipart = copy(contentType = Some(v)) + def header(k: String, v: String): Multipart = copy(additionalHeaders = additionalHeaders + (k -> v)) } diff --git a/core/src/main/scala/com/softwaremill/sttp/RequestT.scala b/core/src/main/scala/com/softwaremill/sttp/RequestT.scala index b785e7c..1461ac6 100644 --- a/core/src/main/scala/com/softwaremill/sttp/RequestT.scala +++ b/core/src/main/scala/com/softwaremill/sttp/RequestT.scala @@ -1,7 +1,6 @@ package com.softwaremill.sttp import java.io.{File, InputStream} -import java.net.URLEncoder import java.nio.ByteBuffer import java.nio.file.Path import java.util.Base64 @@ -200,6 +199,12 @@ case class RequestT[U[_], T, +S]( def body[B: BodySerializer](b: B): RequestT[U, T, S] = withBasicBody(implicitly[BodySerializer[B]].apply(b)) + def multipartBody(ps: Seq[Multipart]): RequestT[U, T, S] = + this.copy(body = MultipartBody(ps)) + + def multipartBody(p1: Multipart, ps: Multipart*): RequestT[U, T, S] = + this.copy(body = MultipartBody(p1 :: ps.toList)) + def streamBody[S2 >: S](b: S2): RequestT[U, T, S2] = copy[U, T, S2](body = StreamBody(b)) @@ -248,16 +253,10 @@ case class RequestT[U[_], T, +S]( private def formDataBody(fs: Seq[(String, String)], encoding: String): RequestT[U, T, S] = { - val b = fs - .map { - case (key, value) => - URLEncoder.encode(key, encoding) + "=" + - URLEncoder.encode(value, encoding) - } - .mkString("&") + val b = RequestBody.paramsToStringBody(fs, encoding) setContentTypeIfMissing(ApplicationFormContentType) - .setContentLengthIfMissing(b.getBytes(encoding).length) - .copy(body = StringBody(b, encoding)) + .setContentLengthIfMissing(b.s.getBytes(encoding).length) + .copy(body = b) } } diff --git a/core/src/main/scala/com/softwaremill/sttp/model/RequestBody.scala b/core/src/main/scala/com/softwaremill/sttp/model/RequestBody.scala index 7499048..5d43298 100644 --- a/core/src/main/scala/com/softwaremill/sttp/model/RequestBody.scala +++ b/core/src/main/scala/com/softwaremill/sttp/model/RequestBody.scala @@ -1,11 +1,14 @@ package com.softwaremill.sttp.model import java.io.InputStream +import java.net.URLEncoder import java.nio.ByteBuffer import java.nio.file.Path import com.softwaremill.sttp._ +import scala.collection.immutable.Seq + sealed trait RequestBody[+S] case object NoBody extends RequestBody[Nothing] @@ -40,3 +43,21 @@ case class PathBody( ) extends BasicRequestBody case class StreamBody[S](s: S) extends RequestBody[S] + +case class MultipartBody(parts: Seq[Multipart]) extends RequestBody[Nothing] + +object RequestBody { + private[sttp] def paramsToStringBody(fs: Seq[(String, String)], + encoding: String): StringBody = { + + val b = fs + .map { + case (key, value) => + URLEncoder.encode(key, encoding) + "=" + + URLEncoder.encode(value, encoding) + } + .mkString("&") + + StringBody(b, encoding) + } +} diff --git a/core/src/main/scala/com/softwaremill/sttp/package.scala b/core/src/main/scala/com/softwaremill/sttp/package.scala index 884d2f9..bbd777e 100644 --- a/core/src/main/scala/com/softwaremill/sttp/package.scala +++ b/core/src/main/scala/com/softwaremill/sttp/package.scala @@ -96,14 +96,14 @@ package object sttp { overwrite: Boolean = false): ResponseAs[Path, Nothing] = ResponseAsFile(path.toFile, overwrite).map(_.toPath) - // multi part factory methods + // multipart factory methods /** * Content type will be set to `text/plain` with `utf-8` encoding, can be * overridden later using the `contentType` method. */ - def multiPart(name: String, data: String): MultiPart = - MultiPart(name, + def multipart(name: String, data: String): Multipart = + Multipart(name, StringBody(data, Utf8), contentType = Some(contentTypeWithEncoding(TextPlainContentType, Utf8))) @@ -112,8 +112,8 @@ package object sttp { * Content type will be set to `text/plain` with `utf-8` encoding, can be * overridden later using the `contentType` method. */ - def multiPart(name: String, data: String, encoding: String): MultiPart = - MultiPart(name, + def multipart(name: String, data: String, encoding: String): Multipart = + Multipart(name, StringBody(data, encoding), contentType = Some(contentTypeWithEncoding(TextPlainContentType, Utf8))) @@ -122,8 +122,8 @@ package object sttp { * Content type will be set to `application/octet-stream`, can be overridden * later using the `contentType` method. */ - def multiPart(name: String, data: Array[Byte]): MultiPart = - MultiPart(name, + def multipart(name: String, data: Array[Byte]): Multipart = + Multipart(name, ByteArrayBody(data), contentType = Some(ApplicationOctetStreamContentType)) @@ -131,8 +131,8 @@ package object sttp { * Content type will be set to `application/octet-stream`, can be overridden * later using the `contentType` method. */ - def multiPart(name: String, data: ByteBuffer): MultiPart = - MultiPart(name, + def multipart(name: String, data: ByteBuffer): Multipart = + Multipart(name, ByteBufferBody(data), contentType = Some(ApplicationOctetStreamContentType)) @@ -140,8 +140,8 @@ package object sttp { * Content type will be set to `application/octet-stream`, can be overridden * later using the `contentType` method. */ - def multiPart(name: String, data: InputStream): MultiPart = - MultiPart(name, + def multipart(name: String, data: InputStream): Multipart = + Multipart(name, InputStreamBody(data), contentType = Some(ApplicationOctetStreamContentType)) @@ -149,19 +149,76 @@ package object sttp { * Content type will be set to `application/octet-stream`, can be overridden * later using the `contentType` method. */ - def multiPart(name: String, data: File): MultiPart = - multiPart(name, data.toPath) + def multipart(name: String, data: File): Multipart = + multipart(name, data.toPath) /** * Content type will be set to `application/octet-stream`, can be overridden * later using the `contentType` method. */ - def multiPart(name: String, data: Path): MultiPart = - MultiPart(name, + def multipart(name: String, data: Path): Multipart = + Multipart(name, PathBody(data), fileName = Some(data.getFileName.toString), contentType = Some(ApplicationOctetStreamContentType)) + /** + * Encodes the given parameters as form data using `utf-8`. + * + * Content type will be set to `application/x-www-form-urlencoded`, can be + * overridden later using the `contentType` method. + */ + def multipart(name: String, fs: Map[String, String]): Multipart = + Multipart(name, + RequestBody.paramsToStringBody(fs.toList, Utf8), + contentType = Some(ApplicationFormContentType)) + + /** + * Encodes the given parameters as form data. + * + * Content type will be set to `application/x-www-form-urlencoded`, can be + * overridden later using the `contentType` method. + */ + def multipart(name: String, + fs: Map[String, String], + encoding: String): Multipart = + Multipart(name, + RequestBody.paramsToStringBody(fs.toList, encoding), + contentType = Some(ApplicationFormContentType)) + + /** + * Encodes the given parameters as form data using `utf-8`. + * + * Content type will be set to `application/x-www-form-urlencoded`, can be + * overridden later using the `contentType` method. + */ + def multipart(name: String, fs: Seq[(String, String)]): Multipart = + Multipart(name, + RequestBody.paramsToStringBody(fs, Utf8), + contentType = Some(ApplicationFormContentType)) + + /** + * Encodes the given parameters as form data. + * + * Content type will be set to `application/x-www-form-urlencoded`, can be + * overridden later using the `contentType` method. + */ + def multipart(name: String, + fs: Seq[(String, String)], + encoding: String): Multipart = + Multipart(name, + RequestBody.paramsToStringBody(fs, encoding), + contentType = Some(ApplicationFormContentType)) + + /** + * Content type will be set to `application/octet-stream`, can be + * overridden later using the `contentType` method. + */ + def multipart[B: BodySerializer](name: String, b: B): Multipart = + Multipart(name, + implicitly[BodySerializer[B]].apply(b), + contentType = Some(ApplicationOctetStreamContentType)) + // util private[sttp] def contentTypeWithEncoding(ct: String, enc: String) = |