diff options
author | adamw <adam@warski.org> | 2017-07-24 17:23:32 +0200 |
---|---|---|
committer | adamw <adam@warski.org> | 2017-07-24 17:23:32 +0200 |
commit | a568123e2a7959b860faaedb66b358fabd92e317 (patch) | |
tree | 308bb70644ed738eef1bfe19f34fa400fb28d90e /core | |
parent | fc62bf67b23793b3766f527de5ffac73e78d2d18 (diff) | |
download | sttp-a568123e2a7959b860faaedb66b358fabd92e317.tar.gz sttp-a568123e2a7959b860faaedb66b358fabd92e317.tar.bz2 sttp-a568123e2a7959b860faaedb66b358fabd92e317.zip |
Automatically setting content-length, where possible
Diffstat (limited to 'core')
-rw-r--r-- | core/src/main/scala/com/softwaremill/sttp/package.scala | 56 | ||||
-rw-r--r-- | core/src/test/scala/com/softwaremill/sttp/RequestTests.scala | 25 |
2 files changed, 73 insertions, 8 deletions
diff --git a/core/src/main/scala/com/softwaremill/sttp/package.scala b/core/src/main/scala/com/softwaremill/sttp/package.scala index f9ee9c6..f55ed9e 100644 --- a/core/src/main/scala/com/softwaremill/sttp/package.scala +++ b/core/src/main/scala/com/softwaremill/sttp/package.scala @@ -156,6 +156,8 @@ package object sttp { header(ContentTypeHeader, contentTypeWithEncoding(ct, encoding), replaceExisting = true) + def contentLength(l: Long): RequestT[U, T, S] = + header(ContentLengthHeader, l.toString, replaceExisting = true) def header(k: String, v: String, replaceExisting: Boolean = false): RequestT[U, T, S] = { @@ -186,27 +188,39 @@ package object sttp { /** * Uses the `utf-8` encoding. + * * If content type is not yet specified, will be set to `text/plain` * with `utf-8` encoding. + * + * If content length is not yet specified, will be set to the number of + * bytes in the string using the `utf-8` encoding. */ def body(b: String): RequestT[U, T, S] = body(b, Utf8) /** * If content type is not yet specified, will be set to `text/plain` * with the given encoding. + * + * If content length is not yet specified, will be set to the number of + * bytes in the string using the given encoding. */ def body(b: String, encoding: String): RequestT[U, T, S] = setContentTypeIfMissing( contentTypeWithEncoding(TextPlainContentType, encoding)) + .setContentLengthIfMissing(b.getBytes(encoding).length) .copy(body = StringBody(b, encoding)) /** * If content type is not yet specified, will be set to * `application/octet-stream`. + * + * If content length is not yet specified, will be set to the length + * of the given array. */ def body(b: Array[Byte]): RequestT[U, T, S] = - setContentTypeIfMissing(ApplicationOctetStreamContentType).copy( - body = ByteArrayBody(b)) + setContentTypeIfMissing(ApplicationOctetStreamContentType) + .setContentLengthIfMissing(b.length) + .copy(body = ByteArrayBody(b)) /** * If content type is not yet specified, will be set to @@ -227,21 +241,32 @@ package object sttp { /** * If content type is not yet specified, will be set to * `application/octet-stream`. + * + * If content length is not yet specified, will be set to the length + * of the given file. */ - def body(b: File): RequestT[U, T, S] = body(b.toPath) + def body(b: File): RequestT[U, T, S] = + body(b.toPath) /** * If content type is not yet specified, will be set to * `application/octet-stream`. + * + * If content length is not yet specified, will be set to the length + * of the given file. */ def body(b: Path): RequestT[U, T, S] = - setContentTypeIfMissing(ApplicationOctetStreamContentType).copy( - body = PathBody(b)) + setContentTypeIfMissing(ApplicationOctetStreamContentType) + .setContentLengthIfMissing(b.toFile.length()) + .copy(body = PathBody(b)) /** * Encodes the given parameters as form data using `utf-8`. * If content type is not yet specified, will be set to * `application/x-www-form-urlencoded`. + * + * If content length is not yet specified, will be set to the length + * of the number of bytes in the url-encoded parameter string. */ def body(fs: Map[String, String]): RequestT[U, T, S] = formDataBody(fs.toList, Utf8) @@ -250,6 +275,9 @@ package object sttp { * Encodes the given parameters as form data. * If content type is not yet specified, will be set to * `application/x-www-form-urlencoded`. + * + * If content length is not yet specified, will be set to the length + * of the number of bytes in the url-encoded parameter string. */ def body(fs: Map[String, String], encoding: String): RequestT[U, T, S] = formDataBody(fs.toList, encoding) @@ -258,6 +286,9 @@ package object sttp { * Encodes the given parameters as form data using `utf-8`. * If content type is not yet specified, will be set to * `application/x-www-form-urlencoded`. + * + * If content length is not yet specified, will be set to the length + * of the number of bytes in the url-encoded parameter string. */ def body(fs: (String, String)*): RequestT[U, T, S] = formDataBody(fs.toList, Utf8) @@ -266,6 +297,9 @@ package object sttp { * Encodes the given parameters as form data. * If content type is not yet specified, will be set to * `application/x-www-form-urlencoded`. + * + * If content length is not yet specified, will be set to the length + * of the number of bytes in the url-encoded parameter string. */ def body(fs: Seq[(String, String)], encoding: String): RequestT[U, T, S] = formDataBody(fs, encoding) @@ -306,10 +340,15 @@ package object sttp { } private def hasContentType: Boolean = - headers.exists(_._1.toLowerCase.contains(ContentTypeHeader)) + headers.exists(_._1.equalsIgnoreCase(ContentTypeHeader)) private def setContentTypeIfMissing(ct: String): RequestT[U, T, S] = if (hasContentType) this else contentType(ct) + private def hasContentLength: Boolean = + headers.exists(_._1.equalsIgnoreCase(ContentLengthHeader)) + private def setContentLengthIfMissing(l: => Long): RequestT[U, T, S] = + if (hasContentLength) this else contentLength(l) + private def formDataBody(fs: Seq[(String, String)], encoding: String): RequestT[U, T, S] = { val b = fs @@ -318,8 +357,9 @@ package object sttp { URLEncoder.encode(p._1, encoding) + "=" + URLEncoder .encode(p._2, encoding)) .mkString("&") - setContentTypeIfMissing(ApplicationFormContentType).copy( - body = StringBody(b, encoding)) + setContentTypeIfMissing(ApplicationFormContentType) + .setContentLengthIfMissing(b.getBytes(encoding).length) + .copy(body = StringBody(b, encoding)) } } diff --git a/core/src/test/scala/com/softwaremill/sttp/RequestTests.scala b/core/src/test/scala/com/softwaremill/sttp/RequestTests.scala index e6db3d7..c6132c9 100644 --- a/core/src/test/scala/com/softwaremill/sttp/RequestTests.scala +++ b/core/src/test/scala/com/softwaremill/sttp/RequestTests.scala @@ -40,4 +40,29 @@ class RequestTests extends FlatSpec with Matchers { .find(_._1 == CookieHeader) .map(_._2) should be(Some("k1=v1; k2=v2")) } + + "content length" should "be automatically set for a string body" in { + sttp + .body("test") + .headers + .find(_._1.equalsIgnoreCase(ContentLengthHeader)) + .map(_._2) should be(Some("4")) + } + + it should "be automatically set to the number of utf-8 bytes in a string" in { + sttp + .body("ąęć") + .headers + .find(_._1.equalsIgnoreCase(ContentLengthHeader)) + .map(_._2) should be(Some("6")) + } + + it should "not override an already specified content length" in { + sttp + .contentLength(10) + .body("a") + .headers + .find(_._1.equalsIgnoreCase(ContentLengthHeader)) + .map(_._2) should be(Some("10")) + } } |