From 7dfc30a36413dc821895fd6dd735f54398af9897 Mon Sep 17 00:00:00 2001 From: Sam Guymer Date: Mon, 21 Sep 2020 17:03:47 +0100 Subject: [PATCH 1/3] Run `scalafmt` --- .../client/akkahttp/AkkaHttpBackend.scala | 27 ++++++----- .../client/DigestAuthenticationBackend.scala | 15 +++--- .../main/scala/sttp/client/RequestBody.scala | 7 ++- .../main/scala/sttp/client/ResponseAs.scala | 4 +- .../sttp/client/SttpClientException.scala | 4 +- .../client/internal/ToCurlConverter.scala | 4 +- .../client/listener/ListenerBackend.scala | 10 ++-- .../sttp/client/AbstractFetchBackend.scala | 5 +- .../client/HttpURLConnectionBackend.scala | 46 +++++++++---------- .../client/examples/PostFormSynchronous.scala | 2 +- .../scala/sttp/client/examples/RetryZio.scala | 31 ++++++------- .../sttp/client/examples/WebsocketZio.scala | 3 +- .../sttp/client/finagle/FinagleBackend.scala | 4 +- .../sttp/client/http4s/Http4sBackend.scala | 4 +- .../opentracing/OpenTracingBackend.scala | 17 ++++--- .../sttp/client/okhttp/OkHttpBackend.scala | 4 +- 16 files changed, 89 insertions(+), 98 deletions(-) diff --git a/akka-http-backend/src/main/scala/sttp/client/akkahttp/AkkaHttpBackend.scala b/akka-http-backend/src/main/scala/sttp/client/akkahttp/AkkaHttpBackend.scala index 48a649dd82..a42926eeb3 100644 --- a/akka-http-backend/src/main/scala/sttp/client/akkahttp/AkkaHttpBackend.scala +++ b/akka-http-backend/src/main/scala/sttp/client/akkahttp/AkkaHttpBackend.scala @@ -103,15 +103,14 @@ class AkkaHttpBackend private ( Future .fromTry(akkaWebsocketRequest) .flatMap(request => http.singleWebsocketRequest(request, handler, connectionSettings(r).connectionSettings)) - .flatMap { - case (wsResponse, wsResult) => - responseFromAkka(r, wsResponse.response).map { r => - if (r.code != StatusCode.SwitchingProtocols) { - throw new NotAWebsocketException(r) - } else { - client.ws.WebSocketResponse(Headers(r.headers), wsResult) - } + .flatMap { case (wsResponse, wsResult) => + responseFromAkka(r, wsResponse.response).map { r => + if (r.code != StatusCode.SwitchingProtocols) { + throw new NotAWebsocketException(r) + } else { + client.ws.WebSocketResponse(Headers(r.headers), wsResult) } + } } } @@ -226,12 +225,12 @@ class AkkaHttpBackend private ( .filterNot(isContentType) .filterNot(isContentLength) .map(h => HttpHeader.parse(h.name, h.value)) - val errors = parsed.collect { - case ParsingResult.Error(e) => e + val errors = parsed.collect { case ParsingResult.Error(e) => + e } if (errors.isEmpty) { - val headers = parsed.collect { - case ParsingResult.Ok(h, _) => h + val headers = parsed.collect { case ParsingResult.Ok(h, _) => + h } Success(headers.toList) @@ -381,8 +380,8 @@ class AkkaHttpBackend private ( object AkkaHttpBackend { type EncodingHandler = PartialFunction[(HttpResponse, HttpEncoding), HttpResponse] object EncodingHandler { - def apply(f: (HttpResponse, HttpEncoding) => HttpResponse): EncodingHandler = { - case (body, encoding) => f(body, encoding) + def apply(f: (HttpResponse, HttpEncoding) => HttpResponse): EncodingHandler = { case (body, encoding) => + f(body, encoding) } } diff --git a/core/src/main/scala/sttp/client/DigestAuthenticationBackend.scala b/core/src/main/scala/sttp/client/DigestAuthenticationBackend.scala index e8ab951658..0f646e66d8 100644 --- a/core/src/main/scala/sttp/client/DigestAuthenticationBackend.scala +++ b/core/src/main/scala/sttp/client/DigestAuthenticationBackend.scala @@ -22,14 +22,13 @@ class DigestAuthenticationBackend[F[_], S, WS_HANDLER[_]]( .flatMap { firstResponse => handleResponse(request, firstResponse, ProxyDigestAuthTag, DigestAuthenticator.proxy(_, clientNonceGenerator)) } - .flatMap { - case (secondResponse, proxyAuthHeader) => - handleResponse( - proxyAuthHeader.map(h => request.header(h)).getOrElse(request), - secondResponse, - DigestAuthTag, - DigestAuthenticator.apply(_, clientNonceGenerator) - ).map(_._1) + .flatMap { case (secondResponse, proxyAuthHeader) => + handleResponse( + proxyAuthHeader.map(h => request.header(h)).getOrElse(request), + secondResponse, + DigestAuthTag, + DigestAuthenticator.apply(_, clientNonceGenerator) + ).map(_._1) } } diff --git a/core/src/main/scala/sttp/client/RequestBody.scala b/core/src/main/scala/sttp/client/RequestBody.scala index 9ca10c9baa..07e0798ce7 100644 --- a/core/src/main/scala/sttp/client/RequestBody.scala +++ b/core/src/main/scala/sttp/client/RequestBody.scala @@ -49,10 +49,9 @@ case class MultipartBody(parts: Seq[Part[BasicRequestBody]]) extends RequestBody object RequestBody { private[client] def paramsToStringBody(fs: Seq[(String, String)], encoding: String): StringBody = { val b = fs - .map { - case (key, value) => - UriCompatibility.encodeQuery(key, encoding) + "=" + - UriCompatibility.encodeQuery(value, encoding) + .map { case (key, value) => + UriCompatibility.encodeQuery(key, encoding) + "=" + + UriCompatibility.encodeQuery(value, encoding) } .mkString("&") diff --git a/core/src/main/scala/sttp/client/ResponseAs.scala b/core/src/main/scala/sttp/client/ResponseAs.scala index 1f7cd9223e..59027d6a93 100644 --- a/core/src/main/scala/sttp/client/ResponseAs.scala +++ b/core/src/main/scala/sttp/client/ResponseAs.scala @@ -116,8 +116,8 @@ object ResponseAs { def deserializeRightWithError[E: ShowError, T]( doDeserialize: String => Either[E, T] ): (Either[String, String], ResponseMetadata) => Either[ResponseError[E], T] = { - case (Left(s), meta) => Left(HttpError(s, meta.code)) - case (Right(s), _) => deserializeWithError(doDeserialize)(implicitly[ShowError[E]])(s) + case (Left(s), meta) => Left(HttpError(s, meta.code)) + case (Right(s), _) => deserializeWithError(doDeserialize)(implicitly[ShowError[E]])(s) } /** diff --git a/core/src/main/scala/sttp/client/SttpClientException.scala b/core/src/main/scala/sttp/client/SttpClientException.scala index dd1bfa243e..d0a456dc00 100644 --- a/core/src/main/scala/sttp/client/SttpClientException.scala +++ b/core/src/main/scala/sttp/client/SttpClientException.scala @@ -55,8 +55,8 @@ object SttpClientException { def adjustExceptions[F[_], T]( monadError: MonadError[F] )(t: => F[T])(usingFn: Exception => Option[Exception]): F[T] = { - monadError.handleError(t) { - case e: Exception => monadError.error(usingFn(e).getOrElse(e)) + monadError.handleError(t) { case e: Exception => + monadError.error(usingFn(e).getOrElse(e)) } } } diff --git a/core/src/main/scala/sttp/client/internal/ToCurlConverter.scala b/core/src/main/scala/sttp/client/internal/ToCurlConverter.scala index 3813efec11..c26ff4d625 100644 --- a/core/src/main/scala/sttp/client/internal/ToCurlConverter.scala +++ b/core/src/main/scala/sttp/client/internal/ToCurlConverter.scala @@ -23,8 +23,8 @@ class ToCurlConverter[R <: RequestT[Identity, _, _]] { r.headers // filtering out compression headers so that the results are human-readable, if possible .filterNot(_.name.equalsIgnoreCase(HeaderNames.AcceptEncoding)) - .collect { - case Header(k, v) => s"""-H '$k: $v'""" + .collect { case Header(k, v) => + s"""-H '$k: $v'""" } .mkString(" ") } diff --git a/core/src/main/scala/sttp/client/listener/ListenerBackend.scala b/core/src/main/scala/sttp/client/listener/ListenerBackend.scala index f021bf54e7..a4745bb92e 100644 --- a/core/src/main/scala/sttp/client/listener/ListenerBackend.scala +++ b/core/src/main/scala/sttp/client/listener/ListenerBackend.scala @@ -16,9 +16,8 @@ class ListenerBackend[F[_], S, WS_HANDLER[_], L]( override def send[T](request: Request[T, S]): F[Response[T]] = { listener.beforeRequest(request).flatMap { t => responseMonad - .handleError(delegate.send(request)) { - case e: Exception => - listener.requestException(request, t, e).flatMap(_ => responseMonad.error(e)) + .handleError(delegate.send(request)) { case e: Exception => + listener.requestException(request, t, e).flatMap(_ => responseMonad.error(e)) } .flatMap { response => listener.requestSuccessful(request, response, t).map(_ => response) } } @@ -29,9 +28,8 @@ class ListenerBackend[F[_], S, WS_HANDLER[_], L]( ): F[WebSocketResponse[WS_RESULT]] = { listener.beforeWebsocket(request).flatMap { t => responseMonad - .handleError(delegate.openWebsocket(request, handler)) { - case e: Exception => - listener.websocketException(request, t, e).flatMap(_ => responseMonad.error(e)) + .handleError(delegate.openWebsocket(request, handler)) { case e: Exception => + listener.websocketException(request, t, e).flatMap(_ => responseMonad.error(e)) } .flatMap { response => listener.websocketSuccessful(request, response, t).map(_ => response) } } diff --git a/core/src/main/scalajs/sttp/client/AbstractFetchBackend.scala b/core/src/main/scalajs/sttp/client/AbstractFetchBackend.scala index 66959f291a..4e09c378cf 100644 --- a/core/src/main/scalajs/sttp/client/AbstractFetchBackend.scala +++ b/core/src/main/scalajs/sttp/client/AbstractFetchBackend.scala @@ -77,9 +77,8 @@ abstract class AbstractFetchBackend[F[_], S](options: FetchOptions, customizeReq } val rheaders = new JSHeaders() - request.headers.foreach { - case Header(name, value) => - rheaders.set(name, value) + request.headers.foreach { case Header(name, value) => + rheaders.set(name, value) } val req = createBody(request.body).map { rbody => diff --git a/core/src/main/scalajvm/sttp/client/HttpURLConnectionBackend.scala b/core/src/main/scalajvm/sttp/client/HttpURLConnectionBackend.scala index fb1d9f5f20..6e6ea1ddb1 100644 --- a/core/src/main/scalajvm/sttp/client/HttpURLConnectionBackend.scala +++ b/core/src/main/scalajvm/sttp/client/HttpURLConnectionBackend.scala @@ -170,20 +170,19 @@ class HttpURLConnectionBackend private ( // https://stackoverflow.com/questions/31406022/how-is-an-http-multipart-content-length-header-value-calculated val contentLength = partsWithHeaders - .map { - case (headers, p) => - val bodyLen: Option[Long] = p.body match { - case StringBody(b, encoding, _) => - Some(b.getBytes(encoding).length.toLong) - case ByteArrayBody(b, _) => Some(b.length.toLong) - case ByteBufferBody(_, _) => None - case InputStreamBody(_, _) => None - case FileBody(b, _) => Some(b.toFile.length()) - } - - val headersLen = headers.getBytes(Iso88591).length - - bodyLen.map(bl => dashesLen + boundaryLen + crLfLen + headersLen + crLfLen + crLfLen + bl + crLfLen) + .map { case (headers, p) => + val bodyLen: Option[Long] = p.body match { + case StringBody(b, encoding, _) => + Some(b.getBytes(encoding).length.toLong) + case ByteArrayBody(b, _) => Some(b.length.toLong) + case ByteBufferBody(_, _) => None + case InputStreamBody(_, _) => None + case FileBody(b, _) => Some(b.toFile.length()) + } + + val headersLen = headers.getBytes(Iso88591).length + + bodyLen.map(bl => dashesLen + boundaryLen + crLfLen + headersLen + crLfLen + crLfLen + bl + crLfLen) } .foldLeft(Option(finalBoundaryLen)) { case (Some(acc), Some(l)) => Some(acc + l) @@ -206,16 +205,15 @@ class HttpURLConnectionBackend private ( total += s.getBytes(Iso88591).length.toLong } - partsWithHeaders.foreach { - case (headers, p) => - writeMeta(dashes) - writeMeta(boundary) - writeMeta(CrLf) - writeMeta(headers) - writeMeta(CrLf) - writeMeta(CrLf) - writeBasicBody(p.body, os) - writeMeta(CrLf) + partsWithHeaders.foreach { case (headers, p) => + writeMeta(dashes) + writeMeta(boundary) + writeMeta(CrLf) + writeMeta(headers) + writeMeta(CrLf) + writeMeta(CrLf) + writeBasicBody(p.body, os) + writeMeta(CrLf) } // final boundary diff --git a/examples/src/main/scala/sttp/client/examples/PostFormSynchronous.scala b/examples/src/main/scala/sttp/client/examples/PostFormSynchronous.scala index 53dc9a6a49..3b4bf15fac 100644 --- a/examples/src/main/scala/sttp/client/examples/PostFormSynchronous.scala +++ b/examples/src/main/scala/sttp/client/examples/PostFormSynchronous.scala @@ -6,7 +6,7 @@ object PostFormSynchronous extends App { val signup = Some("yes") val request = basicRequest - // send the body as form data (x-www-form-urlencoded) + // send the body as form data (x-www-form-urlencoded) .body(Map("name" -> "John", "surname" -> "doe")) // use an optional parameter in the URI .post(uri"https://httpbin.org/post?signup=$signup") diff --git a/examples/src/main/scala/sttp/client/examples/RetryZio.scala b/examples/src/main/scala/sttp/client/examples/RetryZio.scala index 41a1f9ea3f..70e6d1e749 100644 --- a/examples/src/main/scala/sttp/client/examples/RetryZio.scala +++ b/examples/src/main/scala/sttp/client/examples/RetryZio.scala @@ -8,23 +8,22 @@ import zio.duration._ object RetryZio extends zio.App { override def run(args: List[String]): ZIO[zio.ZEnv, Nothing, ExitCode] = { - AsyncHttpClientZioBackend() - .flatMap { implicit backend => - val localhostRequest = basicRequest - .get(uri"http://localhost/test") - .response(asStringAlways) + AsyncHttpClientZioBackend().flatMap { implicit backend => + val localhostRequest = basicRequest + .get(uri"http://localhost/test") + .response(asStringAlways) - val sendWithRetries: ZIO[Clock, Throwable, Response[String]] = localhostRequest - .send() - .either - .repeat( - Schedule.spaced(1.second) *> - Schedule.recurs(10) *> - Schedule.recurWhile(result => RetryWhen.Default(localhostRequest, result)) - ) - .absolve + val sendWithRetries: ZIO[Clock, Throwable, Response[String]] = localhostRequest + .send() + .either + .repeat( + Schedule.spaced(1.second) *> + Schedule.recurs(10) *> + Schedule.recurWhile(result => RetryWhen.Default(localhostRequest, result)) + ) + .absolve - sendWithRetries.ensuring(backend.close().ignore) - }.exitCode + sendWithRetries.ensuring(backend.close().ignore) + }.exitCode } } diff --git a/examples/src/main/scala/sttp/client/examples/WebsocketZio.scala b/examples/src/main/scala/sttp/client/examples/WebsocketZio.scala index 76965d4527..26389a8b44 100644 --- a/examples/src/main/scala/sttp/client/examples/WebsocketZio.scala +++ b/examples/src/main/scala/sttp/client/examples/WebsocketZio.scala @@ -25,6 +25,7 @@ object WebsocketZio extends App { // provide an implementation for the SttpClient dependency; other dependencies are // provided by Zio sendAndPrint - .provideCustomLayer(AsyncHttpClientZioBackend.layer()).exitCode + .provideCustomLayer(AsyncHttpClientZioBackend.layer()) + .exitCode } } diff --git a/finagle-backend/src/main/scala/sttp/client/finagle/FinagleBackend.scala b/finagle-backend/src/main/scala/sttp/client/finagle/FinagleBackend.scala index 2c6ec51433..1468712746 100644 --- a/finagle-backend/src/main/scala/sttp/client/finagle/FinagleBackend.scala +++ b/finagle-backend/src/main/scala/sttp/client/finagle/FinagleBackend.scala @@ -62,8 +62,8 @@ class FinagleBackend(client: Option[Client] = None) extends SttpBackend[TFuture, val body = fromFinagleResponse(request.response, fResponse, responseMetadata) service.close().flatMap(_ => body.map(sttp.client.Response(_, code, statusText, headers, Nil))) } - .rescue { - case e: Exception => service.close().flatMap(_ => TFuture.exception(e)) + .rescue { case e: Exception => + service.close().flatMap(_ => TFuture.exception(e)) } } diff --git a/http4s-backend/src/main/scala/sttp/client/http4s/Http4sBackend.scala b/http4s-backend/src/main/scala/sttp/client/http4s/Http4sBackend.scala index 1cd4ea5f88..88d9d0af0e 100644 --- a/http4s-backend/src/main/scala/sttp/client/http4s/Http4sBackend.scala +++ b/http4s-backend/src/main/scala/sttp/client/http4s/Http4sBackend.scala @@ -241,8 +241,8 @@ object Http4sBackend { type EncodingHandler[F[_]] = PartialFunction[(EntityBody[F], ContentCoding), EntityBody[F]] object EncodingHandler { - def apply[F[_]](f: (EntityBody[F], ContentCoding) => EntityBody[F]): EncodingHandler[F] = { - case (b, c) => f(b, c) + def apply[F[_]](f: (EntityBody[F], ContentCoding) => EntityBody[F]): EncodingHandler[F] = { case (b, c) => + f(b, c) } } diff --git a/metrics/open-tracing-backend/src/main/scala/sttp/client/opentracing/OpenTracingBackend.scala b/metrics/open-tracing-backend/src/main/scala/sttp/client/opentracing/OpenTracingBackend.scala index 9f6d5e41e8..f9199c0252 100644 --- a/metrics/open-tracing-backend/src/main/scala/sttp/client/opentracing/OpenTracingBackend.scala +++ b/metrics/open-tracing-backend/src/main/scala/sttp/client/opentracing/OpenTracingBackend.scala @@ -23,8 +23,8 @@ class OpenTracingBackend[F[_], S] private (delegate: SttpBackend[F, S, NothingT] val spanBuilderTransformer: SpanBuilderTransformer = request .tag(OpenTracingBackend.SpanBuilderTransformerRequestTag) - .collectFirst { - case f: SpanBuilderTransformer => f + .collectFirst { case f: SpanBuilderTransformer => + f } .getOrElse(identity) val span = spanBuilderTransformer( @@ -56,13 +56,12 @@ class OpenTracingBackend[F[_], S] private (delegate: SttpBackend[F, S, NothingT] .finish() response } - ) { - case e => - span - .setTag(Tags.ERROR, java.lang.Boolean.TRUE) - .log(Map("event" -> Tags.ERROR.getKey, "error.object" -> e).asJava) - .finish() - responseMonad.error(e) + ) { case e => + span + .setTag(Tags.ERROR, java.lang.Boolean.TRUE) + .log(Map("event" -> Tags.ERROR.getKey, "error.object" -> e).asJava) + .finish() + responseMonad.error(e) } } diff --git a/okhttp-backend/src/main/scala/sttp/client/okhttp/OkHttpBackend.scala b/okhttp-backend/src/main/scala/sttp/client/okhttp/OkHttpBackend.scala index 464493a9b7..1395fedd45 100644 --- a/okhttp-backend/src/main/scala/sttp/client/okhttp/OkHttpBackend.scala +++ b/okhttp-backend/src/main/scala/sttp/client/okhttp/OkHttpBackend.scala @@ -71,8 +71,8 @@ abstract class OkHttpBackend[F[_], S]( ) request.headers - .foreach { - case Header(name, value) => builder.addHeader(name, value) + .foreach { case Header(name, value) => + builder.addHeader(name, value) } builder.build() From 5a478c1692ca7de34c3d7e0f2a5e59224376fd85 Mon Sep 17 00:00:00 2001 From: Sam Guymer Date: Mon, 21 Sep 2020 16:37:23 +0100 Subject: [PATCH 2/3] Use `AbortController` type from scala-js-dom The `AbortController` type was upstreamed to scala-js-dom and is now available in a released version. --- .../sttp/client/AbstractFetchBackend.scala | 25 ++++--------------- .../dom/experimental/AbortController.scala | 18 ------------- 2 files changed, 5 insertions(+), 38 deletions(-) delete mode 100644 core/src/main/scalajs/sttp/client/dom/experimental/AbortController.scala diff --git a/core/src/main/scalajs/sttp/client/AbstractFetchBackend.scala b/core/src/main/scalajs/sttp/client/AbstractFetchBackend.scala index 4e09c378cf..a0bb836bf2 100644 --- a/core/src/main/scalajs/sttp/client/AbstractFetchBackend.scala +++ b/core/src/main/scalajs/sttp/client/AbstractFetchBackend.scala @@ -4,6 +4,7 @@ import java.nio.ByteBuffer import org.scalajs.dom.FormData import org.scalajs.dom.experimental.{ + AbortController, AbortSignal, BodyInit, Fetch, @@ -21,7 +22,7 @@ import org.scalajs.dom.experimental.{ Response => FetchResponse } import org.scalajs.dom.raw.{Blob, BlobPropertyBag} -import sttp.client.dom.experimental.{AbortController, FilePropertyBag, File => DomFile} +import sttp.client.dom.experimental.{FilePropertyBag, File => DomFile} import sttp.client.internal.{SttpFile, _} import sttp.client.monad.MonadError import sttp.client.monad.syntax._ @@ -84,40 +85,24 @@ abstract class AbstractFetchBackend[F[_], S](options: FetchOptions, customizeReq val req = createBody(request.body).map { rbody => // use manual so we can return a specific error instead of the generic "TypeError: Failed to fetch" val rredirect = if (request.options.followRedirects) RequestRedirect.follow else RequestRedirect.manual + val rsignal = signal.orUndefined - val requestInitStatic = new RequestInit() { + val requestInit = new RequestInit { var method: js.UndefOr[HttpMethod] = request.method.method.asInstanceOf[HttpMethod] - var headers: js.UndefOr[HeadersInit] = rheaders - var body: js.UndefOr[BodyInit] = rbody - var referrer: js.UndefOr[String] = js.undefined - var referrerPolicy: js.UndefOr[ReferrerPolicy] = js.undefined - var mode: js.UndefOr[RequestMode] = options.mode.orUndefined - var credentials: js.UndefOr[RequestCredentials] = options.credentials.orUndefined - var cache: js.UndefOr[RequestCache] = js.undefined - var redirect: js.UndefOr[RequestRedirect] = rredirect - var integrity: js.UndefOr[String] = js.undefined - var keepalive: js.UndefOr[Boolean] = js.undefined - - var signal: js.UndefOr[AbortSignal] = js.undefined - + var signal: js.UndefOr[AbortSignal] = rsignal var window: js.UndefOr[Null] = js.undefined } - val requestInitDynamic = requestInitStatic.asInstanceOf[js.Dynamic] - signal.foreach(s => requestInitDynamic.updateDynamic("signal")(s)) - requestInitDynamic.updateDynamic("redirect")(rredirect) // named wrong in RequestInit - val requestInit = requestInitDynamic.asInstanceOf[RequestInit] - new FetchRequest(request.uri.toString, requestInit) } diff --git a/core/src/main/scalajs/sttp/client/dom/experimental/AbortController.scala b/core/src/main/scalajs/sttp/client/dom/experimental/AbortController.scala deleted file mode 100644 index 4f31ae5f1b..0000000000 --- a/core/src/main/scalajs/sttp/client/dom/experimental/AbortController.scala +++ /dev/null @@ -1,18 +0,0 @@ -package sttp.client.dom.experimental - -import scala.scalajs.js -import scala.scalajs.js.annotation.JSGlobal - -// remove when https://github.com/scala-js/scala-js-dom/pull/328 is merged and released -// also remove `requestInitDynamic` from AbstractFetchBackend - -@js.native -@JSGlobal -class AbortController() extends js.Object { - val signal: AbortSignal = js.native - - def abort(): Unit = js.native -} - -@js.native -trait AbortSignal extends js.Object From 01e5dfbf612809a7bbf4eb214c5b7d7cb2abc97b Mon Sep 17 00:00:00 2001 From: Sam Guymer Date: Mon, 21 Sep 2020 16:37:23 +0100 Subject: [PATCH 3/3] Use scala-js-dom `File` type Creating a `SttpFile` from a JavaScript file currently requires a custom `File` type. This type exists as the one provided by scala-js-dom does not provide the ability to create a file manually. However this makes it annoying to use when you have a scala-js-dom `File`. To improve this, the custom `File` type now extends the scala-js-dom `File` and a `SttpFile` is now created from a scala-js-dom `File`. --- .../scalajs/sttp/client/SttpExtensions.scala | 2 +- .../sttp/client/dom/experimental/File.scala | 6 ++---- .../client/internal/SttpFileExtensions.scala | 3 +-- .../client/testing/HttpTestExtensions.scala | 18 +++++++++--------- 4 files changed, 13 insertions(+), 16 deletions(-) diff --git a/core/src/main/scalajs/sttp/client/SttpExtensions.scala b/core/src/main/scalajs/sttp/client/SttpExtensions.scala index 785f649d49..17d4e812a4 100644 --- a/core/src/main/scalajs/sttp/client/SttpExtensions.scala +++ b/core/src/main/scalajs/sttp/client/SttpExtensions.scala @@ -1,6 +1,6 @@ package sttp.client -import sttp.client.dom.experimental.File +import org.scalajs.dom.File import sttp.client.internal.SttpFile import sttp.model.Part diff --git a/core/src/main/scalajs/sttp/client/dom/experimental/File.scala b/core/src/main/scalajs/sttp/client/dom/experimental/File.scala index aa4cdfcd0f..34abc768cd 100644 --- a/core/src/main/scalajs/sttp/client/dom/experimental/File.scala +++ b/core/src/main/scalajs/sttp/client/dom/experimental/File.scala @@ -1,7 +1,5 @@ package sttp.client.dom.experimental -import org.scalajs.dom.raw.Blob - import scala.scalajs.js import scala.scalajs.js.annotation.JSGlobal @@ -12,9 +10,9 @@ import scala.scalajs.js.annotation.JSGlobal @JSGlobal class File( parts: js.Array[js.Any] = js.native, - val name: String = js.native, + override val name: String = js.native, options: FilePropertyBag = js.native -) extends Blob { +) extends org.scalajs.dom.File { val lastModified: Int = js.native } diff --git a/core/src/main/scalajs/sttp/client/internal/SttpFileExtensions.scala b/core/src/main/scalajs/sttp/client/internal/SttpFileExtensions.scala index bce27a356d..3342bbe49f 100644 --- a/core/src/main/scalajs/sttp/client/internal/SttpFileExtensions.scala +++ b/core/src/main/scalajs/sttp/client/internal/SttpFileExtensions.scala @@ -1,7 +1,6 @@ package sttp.client.internal -import sttp.client.dom.experimental.{File => DomFile} -import sttp.client.dom.experimental.File +import org.scalajs.dom.File // wrap a DomFile trait SttpFileExtensions { self: SttpFile => diff --git a/core/src/test/scalajs/sttp/client/testing/HttpTestExtensions.scala b/core/src/test/scalajs/sttp/client/testing/HttpTestExtensions.scala index 25a0736f7f..376810b038 100644 --- a/core/src/test/scalajs/sttp/client/testing/HttpTestExtensions.scala +++ b/core/src/test/scalajs/sttp/client/testing/HttpTestExtensions.scala @@ -1,9 +1,9 @@ package sttp.client.testing -import org.scalajs.dom.FileReader +import org.scalajs.dom.{Blob, FileReader} import org.scalajs.dom.raw.{Event, UIEvent} import sttp.client._ -import sttp.client.dom.experimental.{FilePropertyBag, File => DomFile} +import sttp.client.dom.experimental.{FilePropertyBag, File => DomFileWithBody} import sttp.client.internal.SparkMD5 import scala.concurrent.{Future, Promise} @@ -16,9 +16,9 @@ import HttpTest.endpoint trait HttpTestExtensions[F[_]] extends AsyncExecutionContext { self: HttpTest[F] => - private def withTemporaryFile[T](content: Option[Array[Byte]])(f: DomFile => Future[T]): Future[T] = { + private def withTemporaryFile[T](content: Option[Array[Byte]])(f: DomFileWithBody => Future[T]): Future[T] = { val data = content.getOrElse(Array.empty) - val file = new DomFile( + val file = new DomFileWithBody( Array(data.toTypedArray.asInstanceOf[js.Any]).toJSArray, "temp.txt", FilePropertyBag( @@ -28,9 +28,9 @@ trait HttpTestExtensions[F[_]] extends AsyncExecutionContext { self: HttpTest[F] f(file) } - private def withTemporaryNonExistentFile[T](f: DomFile => Future[T]): Future[T] = withTemporaryFile(None)(f) + private def withTemporaryNonExistentFile[T](f: DomFileWithBody => Future[T]): Future[T] = withTemporaryFile(None)(f) - private def md5FileHash(file: DomFile): Future[String] = { + private def md5Hash(blob: Blob): Future[String] = { val p = Promise[String]() val fileReader = new FileReader() @@ -41,7 +41,7 @@ trait HttpTestExtensions[F[_]] extends AsyncExecutionContext { self: HttpTest[F] } fileReader.onerror = (_: Event) => p.failure(JavaScriptException("Error reading file")) fileReader.onabort = (_: Event) => p.failure(JavaScriptException("File read aborted")) - fileReader.readAsArrayBuffer(file) + fileReader.readAsArrayBuffer(blob) p.future } @@ -61,7 +61,7 @@ trait HttpTestExtensions[F[_]] extends AsyncExecutionContext { self: HttpTest[F] withTemporaryNonExistentFile { file => val req = basicRequest.get(uri"$endpoint/download/binary").response(asFile(file)) req.send().toFuture().flatMap { resp => - md5FileHash(resp.body.right.get).map { _ shouldBe binaryFileMD5Hash } + md5Hash(resp.body.right.get).map { _ shouldBe binaryFileMD5Hash } } } } @@ -70,7 +70,7 @@ trait HttpTestExtensions[F[_]] extends AsyncExecutionContext { self: HttpTest[F] withTemporaryNonExistentFile { file => val req = basicRequest.get(uri"$endpoint/download/text").response(asFile(file)) req.send().toFuture().flatMap { resp => - md5FileHash(resp.body.right.get).map { _ shouldBe textFileMD5Hash } + md5Hash(resp.body.right.get).map { _ shouldBe textFileMD5Hash } } } }