From 820095216e671888cfa607b329d749ba099a7bc1 Mon Sep 17 00:00:00 2001 From: adamw Date: Sun, 9 Jul 2017 09:32:31 +0200 Subject: Source formatting --- .scalafmt.conf | 0 .../sttp/akkahttp/AkkaHttpSttpHandler.scala | 74 +++++++---- .../com/softwaremill/sttp/akkahttp/package.scala | 6 +- build.sbt | 32 ++--- .../sttp/HttpConnectionSttpHandler.scala | 70 +++++----- .../com/softwaremill/sttp/UriInterpolator.scala | 21 +-- .../com/softwaremill/sttp/model/package.scala | 9 +- .../main/scala/com/softwaremill/sttp/package.scala | 142 +++++++++++++++------ project/plugins.sbt | 2 +- .../scala/com/softwaremill/sttp/BasicTests.scala | 64 +++++++--- .../softwaremill/sttp/UriInterpolatorTests.scala | 2 +- 11 files changed, 273 insertions(+), 149 deletions(-) create mode 100644 .scalafmt.conf diff --git a/.scalafmt.conf b/.scalafmt.conf new file mode 100644 index 0000000..e69de29 diff --git a/akka-http-handler/src/main/scala/com/softwaremill/sttp/akkahttp/AkkaHttpSttpHandler.scala b/akka-http-handler/src/main/scala/com/softwaremill/sttp/akkahttp/AkkaHttpSttpHandler.scala index df40fc9..fc2d632 100644 --- a/akka-http-handler/src/main/scala/com/softwaremill/sttp/akkahttp/AkkaHttpSttpHandler.scala +++ b/akka-http-handler/src/main/scala/com/softwaremill/sttp/akkahttp/AkkaHttpSttpHandler.scala @@ -15,7 +15,8 @@ import com.softwaremill.sttp.model._ import scala.concurrent.Future import scala.util.{Failure, Success, Try} -class AkkaHttpSttpHandler(actorSystem: ActorSystem) extends SttpHandler[Future, Source[ByteString, Any]] { +class AkkaHttpSttpHandler(actorSystem: ActorSystem) + extends SttpHandler[Future, Source[ByteString, Any]] { def this() = this(ActorSystem("sttp")) @@ -23,11 +24,16 @@ class AkkaHttpSttpHandler(actorSystem: ActorSystem) extends SttpHandler[Future, private implicit val materializer = ActorMaterializer() import as.dispatcher - override def send[T](r: Request, responseAs: ResponseAs[T, Source[ByteString, Any]]): Future[Response[T]] = { - requestToAkka(r).map(setBodyOnAkka(r, r.body, _).get).flatMap(Http().singleRequest(_)).flatMap { hr => - val code = hr.status.intValue() - bodyFromAkka(responseAs, hr).map(Response(code, _)) - } + override def send[T](r: Request, + responseAs: ResponseAs[T, Source[ByteString, Any]]) + : Future[Response[T]] = { + requestToAkka(r) + .map(setBodyOnAkka(r, r.body, _).get) + .flatMap(Http().singleRequest(_)) + .flatMap { hr => + val code = hr.status.intValue() + bodyFromAkka(responseAs, hr).map(Response(code, _)) + } } private def methodToAkka(m: Method): HttpMethod = m match { @@ -43,10 +49,12 @@ class AkkaHttpSttpHandler(actorSystem: ActorSystem) extends SttpHandler[Future, case _ => HttpMethod.custom(m.m) } - private def bodyFromAkka[T](rr: ResponseAs[T, Source[ByteString, Any]], hr: HttpResponse): Future[T] = { - def asByteArray = hr.entity.dataBytes - .runFold(ByteString(""))(_ ++ _) - .map(_.toArray[Byte]) + private def bodyFromAkka[T](rr: ResponseAs[T, Source[ByteString, Any]], + hr: HttpResponse): Future[T] = { + def asByteArray = + hr.entity.dataBytes + .runFold(ByteString(""))(_ ++ _) + .map(_.toArray[Byte]) rr match { case IgnoreResponse => @@ -59,14 +67,15 @@ class AkkaHttpSttpHandler(actorSystem: ActorSystem) extends SttpHandler[Future, case ResponseAsByteArray => asByteArray - case r@ResponseAsStream() => + case r @ ResponseAsStream() => Future.successful(r.responseIsStream(hr.entity.dataBytes)) } } private def requestToAkka(r: Request): Future[HttpRequest] = { val ar = HttpRequest(uri = r.uri.toString, method = methodToAkka(r.method)) - val parsed = r.headers.filterNot(isContentType).map(h => HttpHeader.parse(h._1, h._2)) + val parsed = + r.headers.filterNot(isContentType).map(h => HttpHeader.parse(h._1, h._2)) val errors = parsed.collect { case ParsingResult.Error(e) => e } @@ -81,26 +90,34 @@ class AkkaHttpSttpHandler(actorSystem: ActorSystem) extends SttpHandler[Future, } } - private def setBodyOnAkka(r: Request, body: RequestBody, ar: HttpRequest): Try[HttpRequest] = { + private def setBodyOnAkka(r: Request, + body: RequestBody, + ar: HttpRequest): Try[HttpRequest] = { getContentTypeOrOctetStream(r).map { ct => - def doSet(body: RequestBody): HttpRequest = body match { case NoBody => ar case StringBody(b, encoding) => - val ctWithEncoding = HttpCharsets.getForKey(encoding).map(hc => ContentType.apply(ct.mediaType, () => hc)).getOrElse(ct) + val ctWithEncoding = HttpCharsets + .getForKey(encoding) + .map(hc => ContentType.apply(ct.mediaType, () => hc)) + .getOrElse(ct) ar.withEntity(ctWithEncoding, b.getBytes(encoding)) case ByteArrayBody(b) => ar.withEntity(b) case ByteBufferBody(b) => ar.withEntity(ByteString(b)) - case InputStreamBody(b) => ar.withEntity(HttpEntity(ct, StreamConverters.fromInputStream(() => b))) + case InputStreamBody(b) => + ar.withEntity( + HttpEntity(ct, StreamConverters.fromInputStream(() => b))) case FileBody(b) => ar.withEntity(ct, b.toPath) case PathBody(b) => ar.withEntity(ct, b) - case s@SerializableBody(_, _) => doSetSerializable(s) + case s @ SerializableBody(_, _) => doSetSerializable(s) } - def doSetSerializable[T](body: SerializableBody[T]): HttpRequest = body match { - case SerializableBody(SourceBodySerializer, t) => ar.withEntity(HttpEntity(ct, t)) - case SerializableBody(f, t) => doSet(f(t)) - } + def doSetSerializable[T](body: SerializableBody[T]): HttpRequest = + body match { + case SerializableBody(SourceBodySerializer, t) => + ar.withEntity(HttpEntity(ct, t)) + case SerializableBody(f, t) => doSet(f(t)) + } doSet(body) } @@ -111,16 +128,21 @@ class AkkaHttpSttpHandler(actorSystem: ActorSystem) extends SttpHandler[Future, .find(isContentType) .map(_._2) .map { ct => - ContentType.parse(ct).fold( - errors => Failure(new RuntimeException(s"Cannot parse content type: $errors")), - Success(_)) + ContentType + .parse(ct) + .fold( + errors => + Failure( + new RuntimeException(s"Cannot parse content type: $errors")), + Success(_)) } .getOrElse(Success(`application/octet-stream`)) } - private def isContentType(header: (String, String)) = header._1.toLowerCase.contains(`Content-Type`.lowercaseName) + private def isContentType(header: (String, String)) = + header._1.toLowerCase.contains(`Content-Type`.lowercaseName) def close(): Future[Terminated] = { actorSystem.terminate() } -} \ No newline at end of file +} diff --git a/akka-http-handler/src/main/scala/com/softwaremill/sttp/akkahttp/package.scala b/akka-http-handler/src/main/scala/com/softwaremill/sttp/akkahttp/package.scala index 669af5e..0357dd8 100644 --- a/akka-http-handler/src/main/scala/com/softwaremill/sttp/akkahttp/package.scala +++ b/akka-http-handler/src/main/scala/com/softwaremill/sttp/akkahttp/package.scala @@ -5,10 +5,12 @@ import akka.util.ByteString import com.softwaremill.sttp.model.{BasicRequestBody, BodySerializer} package object akkahttp { - private[akkahttp] case object SourceBodySerializer extends BodySerializer[Source[ByteString, Any]] { + private[akkahttp] case object SourceBodySerializer + extends BodySerializer[Source[ByteString, Any]] { def apply(t: Source[ByteString, Any]): BasicRequestBody = throw new RuntimeException("Can only be used with akka-http handler") } - implicit val sourceBodySerializer: BodySerializer[Source[ByteString, Any]] = SourceBodySerializer + implicit val sourceBodySerializer: BodySerializer[Source[ByteString, Any]] = + SourceBodySerializer } diff --git a/build.sbt b/build.sbt index 09f50d0..3aea1fe 100644 --- a/build.sbt +++ b/build.sbt @@ -1,26 +1,26 @@ import scalariform.formatter.preferences._ -lazy val commonSettings = scalariformSettings ++ Seq( +lazy val commonSettings = Seq( organization := "com.softwaremill.sttp", version := "0.1", scalaVersion := "2.12.2", crossScalaVersions := Seq(scalaVersion.value, "2.11.8"), scalacOptions ++= Seq("-unchecked", "-deprecation"), - ScalariformKeys.preferences := ScalariformKeys.preferences.value - .setPreference(DoubleIndentClassDeclaration, true) - .setPreference(PreserveSpaceBeforeArguments, true) - .setPreference(CompactControlReadability, true) - .setPreference(SpacesAroundMultiImports, false), + scalafmtOnCompile := true, // Sonatype OSS deployment publishTo := { val nexus = "https://oss.sonatype.org/" - val (name, url) = if (isSnapshot.value) ("snapshots", nexus + "content/repositories/snapshots") - else ("releases", nexus + "service/local/staging/deploy/maven2") + val (name, url) = + if (isSnapshot.value) + ("snapshots", nexus + "content/repositories/snapshots") + else ("releases", nexus + "service/local/staging/deploy/maven2") Some(name at url) }, credentials += Credentials(Path.userHome / ".ivy2" / ".credentials"), publishMavenStyle := true, - pomIncludeRepository := { _ => false }, + pomIncludeRepository := { _ => + false + }, pomExtra := ( git@github.com/softwaremill/sttp.git @@ -33,8 +33,10 @@ lazy val commonSettings = scalariformSettings ++ Seq( http://www.warski.org - ), - licenses := ("Apache2", new java.net.URL("http://www.apache.org/licenses/LICENSE-2.0.txt")) :: Nil, + ), + licenses := ("Apache2", + new java.net.URL( + "http://www.apache.org/licenses/LICENSE-2.0.txt")) :: Nil, homepage := Some(new java.net.URL("http://softwaremill.com/open-source")) ) @@ -45,9 +47,7 @@ val scalaTest = "org.scalatest" %% "scalatest" % "3.0.3" % "test" lazy val rootProject = (project in file(".")) .settings(commonSettings: _*) - .settings( - publishArtifact := false, - name := "sttp") + .settings(publishArtifact := false, name := "sttp") .aggregate(core, akkaHttpHandler, tests) lazy val core: Project = (project in file("core")) @@ -67,7 +67,7 @@ lazy val akkaHttpHandler: Project = (project in file("akka-http-handler")) libraryDependencies ++= Seq( akkaHttp ) - ) dependsOn(core) + ) dependsOn (core) lazy val tests: Project = (project in file("tests")) .settings(commonSettings: _*) @@ -79,4 +79,4 @@ lazy val tests: Project = (project in file("tests")) "com.typesafe.scala-logging" %% "scala-logging" % "3.5.0" % "test", "com.github.pathikrit" %% "better-files" % "3.0.0" ) - ) dependsOn(core, akkaHttpHandler) \ No newline at end of file + ) dependsOn (core, akkaHttpHandler) diff --git a/core/src/main/scala/com/softwaremill/sttp/HttpConnectionSttpHandler.scala b/core/src/main/scala/com/softwaremill/sttp/HttpConnectionSttpHandler.scala index 8d14907..fdbb322 100644 --- a/core/src/main/scala/com/softwaremill/sttp/HttpConnectionSttpHandler.scala +++ b/core/src/main/scala/com/softwaremill/sttp/HttpConnectionSttpHandler.scala @@ -1,6 +1,11 @@ package com.softwaremill.sttp -import java.io.{ByteArrayOutputStream, InputStream, OutputStream, OutputStreamWriter} +import java.io.{ + ByteArrayOutputStream, + InputStream, + OutputStream, + OutputStreamWriter +} import java.net.HttpURLConnection import java.nio.channels.Channels import java.nio.file.Files @@ -11,7 +16,8 @@ import scala.annotation.tailrec import scala.io.Source object HttpConnectionSttpHandler extends SttpHandler[Id, Nothing] { - override def send[T](r: Request, responseAs: ResponseAs[T, Nothing]): Response[T] = { + override def send[T](r: Request, + responseAs: ResponseAs[T, Nothing]): Response[T] = { val c = r.uri.toURL.openConnection().asInstanceOf[HttpURLConnection] c.setRequestMethod(r.method.m) r.headers.foreach { case (k, v) => c.setRequestProperty(k, v) } @@ -45,14 +51,16 @@ object HttpConnectionSttpHandler extends SttpHandler[Id, Nothing] { case StringBody(b, encoding) => val writer = new OutputStreamWriter(c.getOutputStream, encoding) - try writer.write(b) finally writer.close() + try writer.write(b) + finally writer.close() case ByteArrayBody(b) => c.getOutputStream.write(b) case ByteBufferBody(b) => val channel = Channels.newChannel(c.getOutputStream) - try channel.write(b) finally channel.close() + try channel.write(b) + finally channel.close() case InputStreamBody(b) => copyStream(b, c.getOutputStream) @@ -68,34 +76,36 @@ object HttpConnectionSttpHandler extends SttpHandler[Id, Nothing] { } } - private def readResponse[T](is: InputStream, responseAs: ResponseAs[T, Nothing]): T = responseAs match { - case IgnoreResponse => - @tailrec def consume(): Unit = if (is.read() != -1) consume() - consume() - - case ResponseAsString(enc) => - Source.fromInputStream(is, enc).mkString - - case ResponseAsByteArray => - val os = new ByteArrayOutputStream - var read = 0 - val buf = new Array[Byte](1024) - - @tailrec - def transfer(): Unit = { - read = is.read(buf, 0, buf.length) - if (read != -1) { - os.write(buf, 0, read) - transfer() + private def readResponse[T](is: InputStream, + responseAs: ResponseAs[T, Nothing]): T = + responseAs match { + case IgnoreResponse => + @tailrec def consume(): Unit = if (is.read() != -1) consume() + consume() + + case ResponseAsString(enc) => + Source.fromInputStream(is, enc).mkString + + case ResponseAsByteArray => + val os = new ByteArrayOutputStream + var read = 0 + val buf = new Array[Byte](1024) + + @tailrec + def transfer(): Unit = { + read = is.read(buf, 0, buf.length) + if (read != -1) { + os.write(buf, 0, read) + transfer() + } } - } - transfer() + transfer() - os.toByteArray + os.toByteArray - case ResponseAsStream() => - // only possible when the user requests the response as a stream of Nothing. Oh well ... - throw new IllegalStateException() - } + case ResponseAsStream() => + // only possible when the user requests the response as a stream of Nothing. Oh well ... + throw new IllegalStateException() + } } diff --git a/core/src/main/scala/com/softwaremill/sttp/UriInterpolator.scala b/core/src/main/scala/com/softwaremill/sttp/UriInterpolator.scala index e329630..825985a 100644 --- a/core/src/main/scala/com/softwaremill/sttp/UriInterpolator.scala +++ b/core/src/main/scala/com/softwaremill/sttp/UriInterpolator.scala @@ -7,23 +7,24 @@ object UriInterpolator { private val unreserved = { val alphanum = (('a' to 'z') ++ ('A' to 'Z') ++ ('0' to '9')).toSet - val mark = Set('-', '_', '.', '!', '~', '*', '\'', '(', ')') + val mark = Set('-', '_', '.', '!', '~', '*', '\'', '(', ')') alphanum ++ mark } def interpolate(sc: StringContext, args: String*): URI = { - val strings = sc.parts.iterator + val strings = sc.parts.iterator val expressions = args.iterator - val sb = new StringBuffer(strings.next()) + val sb = new StringBuffer(strings.next()) - while(strings.hasNext){ - for(c <- expressions.next()){ - if(unreserved(c)) + while (strings.hasNext) { + for (c <- expressions.next()) { + if (unreserved(c)) sb.append(c) - else for(b <- c.toString.getBytes("UTF-8")){ - sb.append("%") - sb.append("%02X".format(b)) - } + else + for (b <- c.toString.getBytes("UTF-8")) { + sb.append("%") + sb.append("%02X".format(b)) + } } sb.append(strings.next()) } diff --git a/core/src/main/scala/com/softwaremill/sttp/model/package.scala b/core/src/main/scala/com/softwaremill/sttp/model/package.scala index 913e1b9..0e8a5d0 100644 --- a/core/src/main/scala/com/softwaremill/sttp/model/package.scala +++ b/core/src/main/scala/com/softwaremill/sttp/model/package.scala @@ -29,7 +29,8 @@ package object model { sealed trait RequestBody case object NoBody extends RequestBody // TODO: extract StreamBody, with request parametrized to match the stream type? - case class SerializableBody[T](f: BodySerializer[T], t: T) extends RequestBody + case class SerializableBody[T](f: BodySerializer[T], t: T) + extends RequestBody sealed trait BasicRequestBody extends RequestBody case class StringBody(s: String, encoding: String) extends BasicRequestBody @@ -46,8 +47,10 @@ package object model { sealed trait ResponseAs[T, +S] object IgnoreResponse extends ResponseAs[Unit, Nothing] - case class ResponseAsString(encoding: String) extends ResponseAs[String, Nothing] + case class ResponseAsString(encoding: String) + extends ResponseAs[String, Nothing] object ResponseAsByteArray extends ResponseAs[Array[Byte], Nothing] // response as params - case class ResponseAsStream[T, S]()(implicit val responseIsStream: S =:= T) extends ResponseAs[T, S] + case class ResponseAsStream[T, S]()(implicit val responseIsStream: S =:= T) + extends ResponseAs[T, S] } diff --git a/core/src/main/scala/com/softwaremill/sttp/package.scala b/core/src/main/scala/com/softwaremill/sttp/package.scala index 3321aa7..d757bc0 100644 --- a/core/src/main/scala/com/softwaremill/sttp/package.scala +++ b/core/src/main/scala/com/softwaremill/sttp/package.scala @@ -16,82 +16,125 @@ package object sttp { type Empty[X] = None.type def ignoreResponse: ResponseAs[Unit, Nothing] = IgnoreResponse + /** * Uses `utf-8` encoding. */ def responseAsString: ResponseAs[String, Nothing] = responseAsString(Utf8) - def responseAsString(encoding: String): ResponseAs[String, Nothing] = ResponseAsString(encoding) - def responseAsByteArray: ResponseAs[Array[Byte], Nothing] = ResponseAsByteArray + def responseAsString(encoding: String): ResponseAs[String, Nothing] = + ResponseAsString(encoding) + def responseAsByteArray: ResponseAs[Array[Byte], Nothing] = + ResponseAsByteArray def responseAsStream[S]: ResponseAs[S, S] = ResponseAsStream[S, S]() /** * 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, fileName: Option[String] = None, - contentType: Option[String] = None, additionalHeaders: Map[String, String] = Map()) { + case class MultiPart(name: String, + data: 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 = copy(additionalHeaders = additionalHeaders + (k -> v)) + def header(k: String, v: String): MultiPart = + copy(additionalHeaders = additionalHeaders + (k -> v)) } /** * 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, StringBody(data, Utf8), contentType = Some(contentTypeWithEncoding(TextPlainContentType, Utf8))) + MultiPart(name, + StringBody(data, Utf8), + contentType = + Some(contentTypeWithEncoding(TextPlainContentType, Utf8))) + /** * 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, StringBody(data, encoding), contentType = Some(contentTypeWithEncoding(TextPlainContentType, Utf8))) + MultiPart(name, + StringBody(data, encoding), + contentType = + Some(contentTypeWithEncoding(TextPlainContentType, Utf8))) + /** * 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, ByteArrayBody(data), contentType = Some(ApplicationOctetStreamContentType)) + MultiPart(name, + ByteArrayBody(data), + contentType = Some(ApplicationOctetStreamContentType)) + /** * 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, ByteBufferBody(data), contentType = Some(ApplicationOctetStreamContentType)) + MultiPart(name, + ByteBufferBody(data), + contentType = Some(ApplicationOctetStreamContentType)) + /** * 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, InputStreamBody(data), contentType = Some(ApplicationOctetStreamContentType)) + MultiPart(name, + InputStreamBody(data), + contentType = Some(ApplicationOctetStreamContentType)) + /** * 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, FileBody(data), fileName = Some(data.getName), contentType = Some(ApplicationOctetStreamContentType)) + MultiPart(name, + FileBody(data), + fileName = Some(data.getName), + contentType = Some(ApplicationOctetStreamContentType)) + /** * 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, PathBody(data), fileName = Some(data.getFileName.toString), contentType = Some(ApplicationOctetStreamContentType)) + MultiPart(name, + PathBody(data), + fileName = Some(data.getFileName.toString), + contentType = Some(ApplicationOctetStreamContentType)) case class RequestTemplate[U[_]]( - method: U[Method], - uri: U[URI], - body: RequestBody, - headers: Seq[(String, String)] + method: U[Method], + uri: U[URI], + body: RequestBody, + headers: Seq[(String, String)] ) { def get(uri: URI): Request = this.copy[Id](uri = uri, method = Method.GET) - def head(uri: URI): Request = this.copy[Id](uri = uri, method = Method.HEAD) - def post(uri: URI): Request = this.copy[Id](uri = uri, method = Method.POST) + def head(uri: URI): Request = + this.copy[Id](uri = uri, method = Method.HEAD) + def post(uri: URI): Request = + this.copy[Id](uri = uri, method = Method.POST) def put(uri: URI): Request = this.copy[Id](uri = uri, method = Method.PUT) - def delete(uri: URI): Request = this.copy[Id](uri = uri, method = Method.DELETE) - def options(uri: URI): Request = this.copy[Id](uri = uri, method = Method.OPTIONS) - def patch(uri: URI): Request = this.copy[Id](uri = uri, method = Method.PATCH) + def delete(uri: URI): Request = + this.copy[Id](uri = uri, method = Method.DELETE) + def options(uri: URI): Request = + this.copy[Id](uri = uri, method = Method.OPTIONS) + def patch(uri: URI): Request = + this.copy[Id](uri = uri, method = Method.PATCH) def contentType(ct: String): RequestTemplate[U] = header(ContentTypeHeader, ct, replaceExisting = true) def contentType(ct: String, encoding: String): RequestTemplate[U] = - header(ContentTypeHeader, contentTypeWithEncoding(ct, encoding), replaceExisting = true) - def header(k: String, v: String, replaceExisting: Boolean = false): RequestTemplate[U] = { + header(ContentTypeHeader, + contentTypeWithEncoding(ct, encoding), + replaceExisting = true) + def header(k: String, + v: String, + replaceExisting: Boolean = false): RequestTemplate[U] = { val kLower = k.toLowerCase - val current = if (replaceExisting) headers.filterNot(_._1.toLowerCase.contains(kLower)) else headers + val current = + if (replaceExisting) + headers.filterNot(_._1.toLowerCase.contains(kLower)) + else headers this.copy(headers = current :+ (k -> v)) } @@ -99,44 +142,61 @@ package object sttp { * If content type is not yet specified, will be set to `text/plain` with `utf-8` encoding. */ def body(b: String): RequestTemplate[U] = body(b, Utf8) + /** * If content type is not yet specified, will be set to `text/plain` with the given encoding. */ def body(b: String, encoding: String): RequestTemplate[U] = - setContentTypeIfMissing(contentTypeWithEncoding(TextPlainContentType, encoding)).copy(body = StringBody(b, encoding)) + setContentTypeIfMissing( + contentTypeWithEncoding(TextPlainContentType, encoding)) + .copy(body = StringBody(b, encoding)) + /** * If content type is not yet specified, will be set to `application/octet-stream`. */ def body(b: Array[Byte]): RequestTemplate[U] = - setContentTypeIfMissing(ApplicationOctetStreamContentType).copy(body = ByteArrayBody(b)) + setContentTypeIfMissing(ApplicationOctetStreamContentType).copy( + body = ByteArrayBody(b)) + /** * If content type is not yet specified, will be set to `application/octet-stream`. */ def body(b: ByteBuffer): RequestTemplate[U] = - setContentTypeIfMissing(ApplicationOctetStreamContentType).copy(body = ByteBufferBody(b)) + setContentTypeIfMissing(ApplicationOctetStreamContentType).copy( + body = ByteBufferBody(b)) + /** * If content type is not yet specified, will be set to `application/octet-stream`. */ def body(b: InputStream): RequestTemplate[U] = - setContentTypeIfMissing(ApplicationOctetStreamContentType).copy(body = InputStreamBody(b)) + setContentTypeIfMissing(ApplicationOctetStreamContentType).copy( + body = InputStreamBody(b)) + /** * If content type is not yet specified, will be set to `application/octet-stream`. */ def body(b: File): RequestTemplate[U] = - setContentTypeIfMissing(ApplicationOctetStreamContentType).copy(body = FileBody(b)) + setContentTypeIfMissing(ApplicationOctetStreamContentType).copy( + body = FileBody(b)) + /** * If content type is not yet specified, will be set to `application/octet-stream`. */ def body(b: Path): RequestTemplate[U] = - setContentTypeIfMissing(ApplicationOctetStreamContentType).copy(body = PathBody(b)) + setContentTypeIfMissing(ApplicationOctetStreamContentType).copy( + body = PathBody(b)) + /** * If content type is not yet specified, will be set to `application/octet-stream`. */ def body[T: BodySerializer](b: T): RequestTemplate[U] = - setContentTypeIfMissing(ApplicationOctetStreamContentType).copy(body = SerializableBody(implicitly[BodySerializer[T]], b)) + setContentTypeIfMissing(ApplicationOctetStreamContentType).copy( + body = SerializableBody(implicitly[BodySerializer[T]], b)) - private def hasContentType: Boolean = headers.exists(_._1.toLowerCase.contains(ContentTypeHeader)) - private def setContentTypeIfMissing(ct: String): RequestTemplate[U] = if (hasContentType) this else contentType(ct) + private def hasContentType: Boolean = + headers.exists(_._1.toLowerCase.contains(ContentTypeHeader)) + private def setContentTypeIfMissing(ct: String): RequestTemplate[U] = + if (hasContentType) this else contentType(ct) //def formData(fs: Map[String, Seq[String]]): RequestTemplate[U] = ??? def formData(fs: Map[String, String]): RequestTemplate[U] = ??? @@ -151,20 +211,23 @@ package object sttp { * by the client if such a response type is requested. */ def send[R[_], S, T](responseAs: ResponseAs[T, S])( - implicit handler: SttpHandler[R, S], isRequest: IsRequest[U]): R[Response[T]] = { - + implicit handler: SttpHandler[R, S], + isRequest: IsRequest[U]): R[Response[T]] = { + handler.send(this, responseAs) } } object RequestTemplate { - val empty: RequestTemplate[Empty] = RequestTemplate[Empty](None, None, NoBody, Vector()) + val empty: RequestTemplate[Empty] = + RequestTemplate[Empty](None, None, NoBody, Vector()) } type PartialRequest = RequestTemplate[Empty] type Request = RequestTemplate[Id] - @implicitNotFound("This is a partial request, the method & url are not specified. Use .get(...), .post(...) etc. to obtain a non-partial request.") + @implicitNotFound( + "This is a partial request, the method & url are not specified. Use .get(...), .post(...) etc. to obtain a non-partial request.") private type IsRequest[U[_]] = RequestTemplate[U] =:= Request val sttp: RequestTemplate[Empty] = RequestTemplate.empty @@ -177,9 +240,10 @@ package object sttp { private val TextPlainContentType = "text/plain" private val MultipartFormDataContentType = "multipart/form-data" - private def contentTypeWithEncoding(ct: String, enc: String) = s"$ct; charset=$enc" + private def contentTypeWithEncoding(ct: String, enc: String) = + s"$ct; charset=$enc" implicit class UriContext(val sc: StringContext) extends AnyVal { - def uri(args:String*): URI = UriInterpolator.interpolate(sc, args: _*) + def uri(args: String*): URI = UriInterpolator.interpolate(sc, args: _*) } } diff --git a/project/plugins.sbt b/project/plugins.sbt index d4afe46..a87702c 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,3 +1,3 @@ -addSbtPlugin("org.scalariform" % "sbt-scalariform" % "1.4.0") +addSbtPlugin("com.lucidchart" % "sbt-scalafmt" % "1.7") addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.0.0-RC5") diff --git a/tests/src/test/scala/com/softwaremill/sttp/BasicTests.scala b/tests/src/test/scala/com/softwaremill/sttp/BasicTests.scala index 597c042..39a4b25 100644 --- a/tests/src/test/scala/com/softwaremill/sttp/BasicTests.scala +++ b/tests/src/test/scala/com/softwaremill/sttp/BasicTests.scala @@ -17,20 +17,33 @@ import better.files._ import scala.concurrent.Future import scala.language.higherKinds -class BasicTests extends FlatSpec with Matchers with BeforeAndAfterAll with ScalaFutures with StrictLogging with IntegrationPatience { - private def paramsToString(m: Map[String, String]): String = m.toList.sortBy(_._1).map(p => s"${p._1}=${p._2}").mkString(" ") +class BasicTests + extends FlatSpec + with Matchers + with BeforeAndAfterAll + with ScalaFutures + with StrictLogging + with IntegrationPatience { + private def paramsToString(m: Map[String, String]): String = + m.toList.sortBy(_._1).map(p => s"${p._1}=${p._2}").mkString(" ") private val serverRoutes = path("echo") { get { parameterMap { params => - complete(List("GET", "/echo", paramsToString(params)).filter(_.nonEmpty).mkString(" ")) + complete( + List("GET", "/echo", paramsToString(params)) + .filter(_.nonEmpty) + .mkString(" ")) } } ~ post { parameterMap { params => entity(as[String]) { body: String => - complete(List("POST", "/echo", paramsToString(params), body).filter(_.nonEmpty).mkString(" ")) + complete( + List("POST", "/echo", paramsToString(params), body) + .filter(_.nonEmpty) + .mkString(" ")) } } } @@ -54,14 +67,20 @@ class BasicTests extends FlatSpec with Matchers with BeforeAndAfterAll with Scal def force[T](wrapped: R[T]): T } - runTests("HttpURLConnection", HttpConnectionSttpHandler, new ForceWrappedValue[Id] { - override def force[T](wrapped: Id[T]): T = wrapped - }) - runTests("Akka HTTP", new AkkaHttpSttpHandler(actorSystem), new ForceWrappedValue[Future] { - override def force[T](wrapped: Future[T]): T = wrapped.futureValue - }) - - def runTests[R[_]](name: String, handler: SttpHandler[R, Nothing], forceResponse: ForceWrappedValue[R]): Unit = { + runTests("HttpURLConnection", + HttpConnectionSttpHandler, + new ForceWrappedValue[Id] { + override def force[T](wrapped: Id[T]): T = wrapped + }) + runTests("Akka HTTP", + new AkkaHttpSttpHandler(actorSystem), + new ForceWrappedValue[Future] { + override def force[T](wrapped: Future[T]): T = wrapped.futureValue + }) + + def runTests[R[_]](name: String, + handler: SttpHandler[R, Nothing], + forceResponse: ForceWrappedValue[R]): Unit = { implicit val h = handler val postEcho = sttp.post(new URI(endpoint + "/echo")) @@ -77,13 +96,13 @@ class BasicTests extends FlatSpec with Matchers with BeforeAndAfterAll with Scal name should "parse response as string" in { val response = postEcho.body(testBody).send(responseAsString) val fc = forceResponse.force(response).body - fc should be (expectedPostEchoResponse) + fc should be(expectedPostEchoResponse) } name should "parse response as a byte array" in { val response = postEcho.body(testBody).send(responseAsByteArray) val fc = new String(forceResponse.force(response).body, "UTF-8") - fc should be (expectedPostEchoResponse) + fc should be(expectedPostEchoResponse) } } @@ -94,7 +113,7 @@ class BasicTests extends FlatSpec with Matchers with BeforeAndAfterAll with Scal .send(responseAsString) val fc = forceResponse.force(response).body - fc should be ("GET /echo p1=v1 p2=v2") + fc should be("GET /echo p1=v1 p2=v2") } } @@ -102,25 +121,28 @@ class BasicTests extends FlatSpec with Matchers with BeforeAndAfterAll with Scal name should "post a string" in { val response = postEcho.body(testBody).send(responseAsString) val fc = forceResponse.force(response).body - fc should be (expectedPostEchoResponse) + fc should be(expectedPostEchoResponse) } name should "post a byte array" in { val response = postEcho.body(testBodyBytes).send(responseAsString) val fc = forceResponse.force(response).body - fc should be (expectedPostEchoResponse) + fc should be(expectedPostEchoResponse) } name should "post an input stream" in { - val response = postEcho.body(new ByteArrayInputStream(testBodyBytes)).send(responseAsString) + val response = postEcho + .body(new ByteArrayInputStream(testBodyBytes)) + .send(responseAsString) val fc = forceResponse.force(response).body - fc should be (expectedPostEchoResponse) + fc should be(expectedPostEchoResponse) } name should "post a byte buffer" in { - val response = postEcho.body(ByteBuffer.wrap(testBodyBytes)).send(responseAsString) + val response = + postEcho.body(ByteBuffer.wrap(testBodyBytes)).send(responseAsString) val fc = forceResponse.force(response).body - fc should be (expectedPostEchoResponse) + fc should be(expectedPostEchoResponse) } name should "post a file" in { diff --git a/tests/src/test/scala/com/softwaremill/sttp/UriInterpolatorTests.scala b/tests/src/test/scala/com/softwaremill/sttp/UriInterpolatorTests.scala index 8ad8aea..0f30f8a 100644 --- a/tests/src/test/scala/com/softwaremill/sttp/UriInterpolatorTests.scala +++ b/tests/src/test/scala/com/softwaremill/sttp/UriInterpolatorTests.scala @@ -20,7 +20,7 @@ class UriInterpolatorTests extends FlatSpec with Matchers { for (((interpolated, expected), i) <- testData.zipWithIndex) { it should s"interpolate to $expected ($i)" in { - interpolated should be (new URI(expected)) + interpolated should be(new URI(expected)) } } } -- cgit v1.2.3