aboutsummaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorBjørn Madsen <bm@aeons.dk>2017-08-09 22:17:53 +0200
committerBjørn Madsen <bm@aeons.dk>2017-08-09 22:17:53 +0200
commit85f93f2ccd282cdfceda8ae76cdf3cbb36d20883 (patch)
treef656e434375c0515051f30eab6f09406d1c759b5 /core
parent18db8e9d1ee240d11b558cdb9b5c850c5b063080 (diff)
downloadsttp-85f93f2ccd282cdfceda8ae76cdf3cbb36d20883.tar.gz
sttp-85f93f2ccd282cdfceda8ae76cdf3cbb36d20883.tar.bz2
sttp-85f93f2ccd282cdfceda8ae76cdf3cbb36d20883.zip
Move default content type to BasicRequestBody
Revert BodySerializer to be a function, and remove SerializableBody
Diffstat (limited to 'core')
-rw-r--r--core/src/main/scala/com/softwaremill/sttp/BodySerializer.scala29
-rw-r--r--core/src/main/scala/com/softwaremill/sttp/HttpURLConnectionSttpHandler.scala13
-rw-r--r--core/src/main/scala/com/softwaremill/sttp/RequestT.scala54
-rw-r--r--core/src/main/scala/com/softwaremill/sttp/model/RequestBody.scala41
-rw-r--r--core/src/main/scala/com/softwaremill/sttp/package.scala6
5 files changed, 71 insertions, 72 deletions
diff --git a/core/src/main/scala/com/softwaremill/sttp/BodySerializer.scala b/core/src/main/scala/com/softwaremill/sttp/BodySerializer.scala
deleted file mode 100644
index 040c563..0000000
--- a/core/src/main/scala/com/softwaremill/sttp/BodySerializer.scala
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.softwaremill.sttp
-
-import com.softwaremill.sttp.model.BasicRequestBody
-
-/**
- * Provide an implicit value of this type to serialize arbitrary classes into a request body.
- * Handlers might also provide special logic for serializer instances which they define (e.g. to handle streaming).
- */
-trait BodySerializer[B] {
- def apply(body: B): BasicRequestBody
- def defaultContentType: Option[String]
-}
-
-object BodySerializer {
- final def apply[B](implicit instance: BodySerializer[B]): BodySerializer[B] =
- instance
-
- final def instance[B](f: B => BasicRequestBody) =
- new BodySerializer[B] {
- def apply(body: B): BasicRequestBody = f(body)
- val defaultContentType: Option[String] = None
- }
-
- final def instance[B](f: B => BasicRequestBody, contentType: String) =
- new BodySerializer[B] {
- def apply(body: B): BasicRequestBody = f(body)
- val defaultContentType: Option[String] = Option(contentType)
- }
-}
diff --git a/core/src/main/scala/com/softwaremill/sttp/HttpURLConnectionSttpHandler.scala b/core/src/main/scala/com/softwaremill/sttp/HttpURLConnectionSttpHandler.scala
index 29da886..dd208f4 100644
--- a/core/src/main/scala/com/softwaremill/sttp/HttpURLConnectionSttpHandler.scala
+++ b/core/src/main/scala/com/softwaremill/sttp/HttpURLConnectionSttpHandler.scala
@@ -56,28 +56,25 @@ object HttpURLConnectionSttpHandler extends SttpHandler[Id, Nothing] {
body match {
case NoBody => // skip
- case StringBody(b, encoding) =>
+ case StringBody(b, encoding, _) =>
val writer = new OutputStreamWriter(c.getOutputStream, encoding)
try writer.write(b)
finally writer.close()
- case ByteArrayBody(b) =>
+ case ByteArrayBody(b, _) =>
c.getOutputStream.write(b)
- case ByteBufferBody(b) =>
+ case ByteBufferBody(b, _) =>
val channel = Channels.newChannel(c.getOutputStream)
try channel.write(b)
finally channel.close()
- case InputStreamBody(b) =>
+ case InputStreamBody(b, _) =>
copyStream(b, c.getOutputStream)
- case PathBody(b) =>
+ case PathBody(b, _) =>
Files.copy(b, c.getOutputStream)
- case SerializableBody(f, t) =>
- setBody(f(t), c)
-
case StreamBody(s) =>
// we have an instance of nothing - everything's possible!
s
diff --git a/core/src/main/scala/com/softwaremill/sttp/RequestT.scala b/core/src/main/scala/com/softwaremill/sttp/RequestT.scala
index c17be59..6b1bf0c 100644
--- a/core/src/main/scala/com/softwaremill/sttp/RequestT.scala
+++ b/core/src/main/scala/com/softwaremill/sttp/RequestT.scala
@@ -100,10 +100,8 @@ case class RequestT[U[_], T, +S](
* bytes in the string using the given encoding.
*/
def body(b: String, encoding: String): RequestT[U, T, S] =
- setContentTypeIfMissing(
- contentTypeWithEncoding(TextPlainContentType, encoding))
+ withBasicBody(StringBody(b, encoding))
.setContentLengthIfMissing(b.getBytes(encoding).length)
- .copy(body = StringBody(b, encoding))
/**
* If content type is not yet specified, will be set to
@@ -113,25 +111,22 @@ case class RequestT[U[_], T, +S](
* of the given array.
*/
def body(b: Array[Byte]): RequestT[U, T, S] =
- setContentTypeIfMissing(ApplicationOctetStreamContentType)
+ withBasicBody(ByteArrayBody(b))
.setContentLengthIfMissing(b.length)
- .copy(body = ByteArrayBody(b))
/**
* If content type is not yet specified, will be set to
* `application/octet-stream`.
*/
def body(b: ByteBuffer): RequestT[U, T, S] =
- setContentTypeIfMissing(ApplicationOctetStreamContentType).copy(
- body = ByteBufferBody(b))
+ withBasicBody(ByteBufferBody(b))
/**
* If content type is not yet specified, will be set to
* `application/octet-stream`.
*/
def body(b: InputStream): RequestT[U, T, S] =
- setContentTypeIfMissing(ApplicationOctetStreamContentType).copy(
- body = InputStreamBody(b))
+ withBasicBody(InputStreamBody(b))
/**
* If content type is not yet specified, will be set to
@@ -151,9 +146,8 @@ case class RequestT[U[_], T, +S](
* of the given file.
*/
def body(b: Path): RequestT[U, T, S] =
- setContentTypeIfMissing(ApplicationOctetStreamContentType)
+ withBasicBody(PathBody(b))
.setContentLengthIfMissing(b.toFile.length())
- .copy(body = PathBody(b))
/**
* Encodes the given parameters as form data using `utf-8`.
@@ -203,16 +197,11 @@ case class RequestT[U[_], T, +S](
* If content type is not yet specified, will be set to
* `application/octet-stream`.
*/
- def body[B](b: B)(implicit serializer: BodySerializer[B]): RequestT[U, T, S] =
- setContentTypeIfMissing(
- serializer.defaultContentType.getOrElse(
- ApplicationOctetStreamContentType))
- .copy(body = SerializableBody(serializer, b))
-
- //def multipartData(parts: MultiPart*): RequestTemplate[U] = ???
+ def body[B: BodySerializer](b: B): RequestT[U, T, S] =
+ withBasicBody(implicitly[BodySerializer[B]].apply(b))
def streamBody[S2 >: S](b: S2): RequestT[U, T, S2] =
- this.copy[U, T, S2](body = StreamBody(b))
+ copy[U, T, S2](body = StreamBody(b))
/**
* What's the target type to which the response body should be read.
@@ -236,11 +225,25 @@ case class RequestT[U[_], T, +S](
handler.send(this.asInstanceOf[RequestT[Id, T, S]])
}
- private[sttp] def hasContentType: Boolean =
+ private def hasContentType: Boolean =
headers.exists(_._1.equalsIgnoreCase(ContentTypeHeader))
- private[sttp] def setContentTypeIfMissing(ct: String): RequestT[U, T, S] =
+ private def setContentTypeIfMissing(ct: String): RequestT[U, T, S] =
if (hasContentType) this else contentType(ct)
+ private def withBasicBody(body: BasicRequestBody) = {
+ if (hasContentType) this
+ else
+ body match {
+ case StringBody(_, encoding, Some(ct)) =>
+ contentType(ct, encoding)
+ case body =>
+ body.defaultContentType match {
+ case Some(ct) => contentType(ct)
+ case None => this
+ }
+ }
+ }.copy(body = body)
+
private def hasContentLength: Boolean =
headers.exists(_._1.equalsIgnoreCase(ContentLengthHeader))
private def setContentLengthIfMissing(l: => Long): RequestT[U, T, S] =
@@ -249,10 +252,11 @@ case class RequestT[U[_], T, +S](
private def formDataBody(fs: Seq[(String, String)],
encoding: String): RequestT[U, T, S] = {
val b = fs
- .map(
- p =>
- URLEncoder.encode(p._1, encoding) + "=" + URLEncoder
- .encode(p._2, encoding))
+ .map {
+ case (key, value) =>
+ URLEncoder.encode(key, encoding) + "=" +
+ URLEncoder.encode(value, encoding)
+ }
.mkString("&")
setContentTypeIfMissing(ApplicationFormContentType)
.setContentLengthIfMissing(b.getBytes(encoding).length)
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 0c737f0..7499048 100644
--- a/core/src/main/scala/com/softwaremill/sttp/model/RequestBody.scala
+++ b/core/src/main/scala/com/softwaremill/sttp/model/RequestBody.scala
@@ -4,18 +4,39 @@ import java.io.InputStream
import java.nio.ByteBuffer
import java.nio.file.Path
-import com.softwaremill.sttp.BodySerializer
+import com.softwaremill.sttp._
sealed trait RequestBody[+S]
case object NoBody extends RequestBody[Nothing]
-case class SerializableBody[T](f: BodySerializer[T], t: T)
- extends RequestBody[Nothing]
-
-sealed trait BasicRequestBody extends RequestBody[Nothing]
-case class StringBody(s: String, encoding: String) extends BasicRequestBody
-case class ByteArrayBody(b: Array[Byte]) extends BasicRequestBody
-case class ByteBufferBody(b: ByteBuffer) extends BasicRequestBody
-case class InputStreamBody(b: InputStream) extends BasicRequestBody
-case class PathBody(f: Path) extends BasicRequestBody
+
+sealed trait BasicRequestBody extends RequestBody[Nothing] {
+ def defaultContentType: Option[String]
+}
+
+case class StringBody(
+ s: String,
+ encoding: String,
+ defaultContentType: Option[String] = Some(TextPlainContentType)
+) extends BasicRequestBody
+
+case class ByteArrayBody(
+ b: Array[Byte],
+ defaultContentType: Option[String] = Some(ApplicationOctetStreamContentType)
+) extends BasicRequestBody
+
+case class ByteBufferBody(
+ b: ByteBuffer,
+ defaultContentType: Option[String] = Some(ApplicationOctetStreamContentType)
+) extends BasicRequestBody
+
+case class InputStreamBody(
+ b: InputStream,
+ defaultContentType: Option[String] = Some(ApplicationOctetStreamContentType)
+) extends BasicRequestBody
+
+case class PathBody(
+ f: Path,
+ defaultContentType: Option[String] = Some(ApplicationOctetStreamContentType)
+) extends BasicRequestBody
case class StreamBody[S](s: S) extends RequestBody[S]
diff --git a/core/src/main/scala/com/softwaremill/sttp/package.scala b/core/src/main/scala/com/softwaremill/sttp/package.scala
index cca86dd..884d2f9 100644
--- a/core/src/main/scala/com/softwaremill/sttp/package.scala
+++ b/core/src/main/scala/com/softwaremill/sttp/package.scala
@@ -22,6 +22,12 @@ package object sttp {
".get(...), .post(...) etc. to obtain a non-partial request.")
private[sttp] type IsIdInRequest[U[_]] = U[Unit] =:= Id[Unit]
+ /**
+ * Provide an implicit value of this type to serialize arbitrary classes into a request body.
+ * Handlers might also provide special logic for serializer instances which they define (e.g. to handle streaming).
+ */
+ type BodySerializer[B] = B => BasicRequestBody
+
// constants
private[sttp] val ContentTypeHeader = "Content-Type"