diff options
author | adamw <adam@warski.org> | 2017-07-09 09:32:31 +0200 |
---|---|---|
committer | adamw <adam@warski.org> | 2017-07-09 09:32:31 +0200 |
commit | 820095216e671888cfa607b329d749ba099a7bc1 (patch) | |
tree | 9276e9ec7be44ccc78dfdf9f2a93475deb36d6ff /core/src/main/scala/com | |
parent | 08dd8ea1b55e62925aeee72de5d63a1e1961b060 (diff) | |
download | sttp-820095216e671888cfa607b329d749ba099a7bc1.tar.gz sttp-820095216e671888cfa607b329d749ba099a7bc1.tar.bz2 sttp-820095216e671888cfa607b329d749ba099a7bc1.zip |
Source formatting
Diffstat (limited to 'core/src/main/scala/com')
4 files changed, 160 insertions, 82 deletions
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: _*) } } |