aboutsummaryrefslogtreecommitdiff
path: root/core/src
diff options
context:
space:
mode:
authoradamw <adam@warski.org>2017-07-04 13:46:27 +0200
committeradamw <adam@warski.org>2017-07-04 13:46:27 +0200
commit09da476faedc382d7f2604be142a353e5851a1e3 (patch)
treebb70efb1e7bcb100c6fb2234aa277daaa84a393b /core/src
parent446dfa70716928c9a92c30ced94a7be6e62d73f0 (diff)
downloadsttp-09da476faedc382d7f2604be142a353e5851a1e3.tar.gz
sttp-09da476faedc382d7f2604be142a353e5851a1e3.tar.bz2
sttp-09da476faedc382d7f2604be142a353e5851a1e3.zip
First version of unified send
Diffstat (limited to 'core/src')
-rw-r--r--core/src/main/scala/com/softwaremill/sttp/HttpConnectionSttpHandler.scala6
-rw-r--r--core/src/main/scala/com/softwaremill/sttp/SttpHandler.scala33
-rw-r--r--core/src/main/scala/com/softwaremill/sttp/model/package.scala14
-rw-r--r--core/src/main/scala/com/softwaremill/sttp/package.scala72
4 files changed, 53 insertions, 72 deletions
diff --git a/core/src/main/scala/com/softwaremill/sttp/HttpConnectionSttpHandler.scala b/core/src/main/scala/com/softwaremill/sttp/HttpConnectionSttpHandler.scala
index 362bdab..f7292d7 100644
--- a/core/src/main/scala/com/softwaremill/sttp/HttpConnectionSttpHandler.scala
+++ b/core/src/main/scala/com/softwaremill/sttp/HttpConnectionSttpHandler.scala
@@ -10,8 +10,8 @@ import com.softwaremill.sttp.model._
import scala.annotation.tailrec
import scala.io.Source
-object HttpConnectionSttpHandler extends SttpHandler[Id] {
- override def send[T](r: Request, responseAs: ResponseAs[T]): Response[T] = {
+object HttpConnectionSttpHandler extends SttpHandler[Id, Any, ResponseAsBasic] {
+ override def send[T](r: Request, responseAs: ResponseAsBasic[T, Any]): 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) }
@@ -68,7 +68,7 @@ object HttpConnectionSttpHandler extends SttpHandler[Id] {
}
}
- private def readResponse[T](is: InputStream, responseAs: ResponseAs[T]): T = responseAs match {
+ private def readResponse[T](is: InputStream, responseAs: ResponseAsBasic[T, Any]): T = responseAs match {
case IgnoreResponse =>
@tailrec def consume(): Unit = if (is.read() != -1) consume()
consume()
diff --git a/core/src/main/scala/com/softwaremill/sttp/SttpHandler.scala b/core/src/main/scala/com/softwaremill/sttp/SttpHandler.scala
index 05c7199..50ccd35 100644
--- a/core/src/main/scala/com/softwaremill/sttp/SttpHandler.scala
+++ b/core/src/main/scala/com/softwaremill/sttp/SttpHandler.scala
@@ -4,10 +4,33 @@ import com.softwaremill.sttp.model.{ResponseAs, ResponseAsStream}
import scala.language.higherKinds
-trait SttpHandler[R[_]] {
- def send[T](request: Request, responseAs: ResponseAs[T]): R[Response[T]]
+trait SttpHandler[R[_], +S, -AcceptsResponseAs[x, -s] <: ResponseAs[x, s]] {
+ def send[T](request: Request, responseAs: AcceptsResponseAs[T, S]): R[Response[T]]
}
-trait SttpStreamHandler[R[_], S] extends SttpHandler[R] {
- def send(request: Request, responseAsStream: ResponseAsStream[S]): R[Response[S]]
-} \ No newline at end of file
+//trait SttpStreamHandler[R[_], S] extends SttpHandler[R] {
+// def send(request: Request, responseAsStream: ResponseAsStream[S]): R[Response[S]]
+//}
+
+
+/*
+
+Cat <: Animal
+Dog <: Animal
+
+x: Animal := Cat
+
+Contravariant:
+def eat(x: Cat) := def eat(x: Animal)
+Animal => Cat := Animal => Unit
+
+Covariant:
+def create: Animal := def create: Cat
+Unit => Animal := Unit => Cat
+
+---
+
+RA >: RAS
+Handler[RAS] >: Handler[RA]
+
+ */ \ No newline at end of file
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 e50426c..3c0e563 100644
--- a/core/src/main/scala/com/softwaremill/sttp/model/package.scala
+++ b/core/src/main/scala/com/softwaremill/sttp/model/package.scala
@@ -4,6 +4,8 @@ import java.io.{File, InputStream}
import java.nio.ByteBuffer
import java.nio.file.Path
+import scala.language.higherKinds
+
package object model {
case class Method(m: String) extends AnyVal
object Method {
@@ -36,11 +38,13 @@ package object model {
case class FileBody(f: File) extends BasicRequestBody
case class PathBody(f: Path) extends BasicRequestBody
- sealed trait ResponseAs[T]
- object IgnoreResponse extends ResponseAs[Unit]
- case class ResponseAsString(encoding: String) extends ResponseAs[String]
- object ResponseAsByteArray extends ResponseAs[Array[Byte]]
+ sealed trait ResponseAs[T, -S]
+
+ sealed trait ResponseAsBasic[T, -S <: Any] extends ResponseAs[T, S]
+ object IgnoreResponse extends ResponseAsBasic[Unit, Any]
+ case class ResponseAsString(encoding: String) extends ResponseAsBasic[String, Any]
+ object ResponseAsByteArray extends ResponseAsBasic[Array[Byte], Any]
// response as params
- case class ResponseAsStream[S]()
+ case class ResponseAsStream[T, S]()(implicit val x: 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 40b8d82..e4f5311 100644
--- a/core/src/main/scala/com/softwaremill/sttp/package.scala
+++ b/core/src/main/scala/com/softwaremill/sttp/package.scala
@@ -12,62 +12,17 @@ import scala.language.higherKinds
import scala.collection.immutable.Seq
package object sttp {
- /*
-
- - set headers
- - set cookies (set from response)
- - partial request (no uri + method) / full request
- - start with an empty partial request
- - multi-part uploads
- - body: bytes, input stream (?), task/future, stream (fs2/akka), form data, file
- - auth
- - access uri/method/headers/cookies/body spec
- - proxy
- - user agent, buffer size
- - charset
- - zipped encodings
- - SSL - mutual? (client side)
-
- - stream responses (sendStreamAndReceive?) / strict responses
- - make sure response is consumed - only fire request when we know what to do with response?
-
- - reuse connections / connection pooling - in handler
-
- - handler restriction? AnyHandler <: Handler Restriction
-
- Options:
- - timeouts (connection/read)
- - follow redirect
- - ignore SSL
-
- //
-
- We want to serialize to:
- - string
- - byte array
- - input stream
- - handler-specific stream of bytes/strings
-
- post:
- - data (bytes/is/string - but which encoding?)
- - form data (kv pairs - application/x-www-form-urlencoded)
- - multipart (files mixed with forms - multipart/form-data)
-
- */
-
- //
-
type Id[X] = X
type Empty[X] = None.type
- def ignoreResponse: ResponseAs[Unit] = IgnoreResponse
+ def ignoreResponse: ResponseAsBasic[Unit, Any] = IgnoreResponse
/**
* Uses `utf-8` encoding.
*/
- def responseAsString: ResponseAs[String] = responseAsString(Utf8)
- def responseAsString(encoding: String): ResponseAs[String] = ResponseAsString(encoding)
- def responseAsByteArray: ResponseAs[Array[Byte]] = ResponseAsByteArray
- def responseAsStream[S]: ResponseAsStream[S] = ResponseAsStream[S]()
+ def responseAsString: ResponseAsBasic[String, Any] = responseAsString(Utf8)
+ def responseAsString(encoding: String): ResponseAsBasic[String, Any] = ResponseAsString(encoding)
+ def responseAsByteArray: ResponseAsBasic[Array[Byte], Any] = 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
@@ -189,15 +144,14 @@ package object sttp {
def multipartData(parts: MultiPart*): RequestTemplate[U] = ???
- def send[R[_], T](responseAs: ResponseAs[T])(
- implicit handler: SttpHandler[R], isRequest: IsRequest[U]): R[Response[T]] = {
-
- handler.send(this, responseAs)
- }
-
- def send[R[_], S](responseAs: ResponseAsStream[S])(
- implicit handler: SttpStreamHandler[R, S], isRequest: IsRequest[U]): R[Response[S]] = {
-
+ /**
+ * @param responseAs What's the target type to which the response should be read. Needs to be specified upfront
+ * so that the response is always consumed and hence there are no requirements on client code
+ * to consume it. An exception to this are streaming responses, which need to fully consumed
+ * by the client if such a response type is requested.
+ */
+ def send[R[_], S, T, ResponseAsType[x, -s] <: ResponseAs[x, s]](responseAs: ResponseAsType[T, S])(
+ implicit handler: SttpHandler[R, S, ResponseAsType], isRequest: IsRequest[U]): R[Response[T]] = {
handler.send(this, responseAs)
}
}