aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoradamw <adam@warski.org>2017-10-06 14:19:44 +0200
committeradamw <adam@warski.org>2017-10-06 14:19:44 +0200
commitbb7abc189d9a5f079caa47a4508b5ae585dc8bcf (patch)
tree4d096e1b0c78156df923a7cf3282a86507b8ef8b
parent43baccc0edf12e8951c903d6697d7ee24a201e63 (diff)
downloadsttp-bb7abc189d9a5f079caa47a4508b5ae585dc8bcf.tar.gz
sttp-bb7abc189d9a5f079caa47a4508b5ae585dc8bcf.tar.bz2
sttp-bb7abc189d9a5f079caa47a4508b5ae585dc8bcf.zip
#10: add proxy support
-rw-r--r--README.md20
-rw-r--r--akka-http-backend/src/main/scala/com/softwaremill/sttp/akkahttp/AkkaHttpBackend.scala33
-rw-r--r--async-http-client-backend/cats/src/main/scala/com/softwaremill/sttp/asynchttpclient/cats/AsyncHttpClientCatsBackend.scala11
-rw-r--r--async-http-client-backend/fs2/src/main/scala/com/softwaremill/sttp/asynchttpclient/fs2/AsyncHttpClientFs2Backend.scala11
-rw-r--r--async-http-client-backend/future/src/main/scala/com/softwaremill/sttp/asynchttpclient/future/AsyncHttpClientFutureBackend.scala16
-rw-r--r--async-http-client-backend/monix/src/main/scala/com/softwaremill/sttp/asynchttpclient/monix/AsyncHttpClientMonixBackend.scala10
-rw-r--r--async-http-client-backend/scalaz/src/main/scala/com/softwaremill/sttp/asynchttpclient/scalaz/AsyncHttpClientScalazBackend.scala12
-rw-r--r--async-http-client-backend/src/main/scala/com/softwaremill/sttp/asynchttpclient/AsyncHttpClientBackend.scala23
-rw-r--r--core/src/main/scala/com/softwaremill/sttp/HttpURLConnectionBackend.scala27
-rw-r--r--core/src/main/scala/com/softwaremill/sttp/SttpBackend.scala5
-rw-r--r--core/src/main/scala/com/softwaremill/sttp/SttpBackendOptions.scala45
-rw-r--r--okhttp-backend/monix/src/main/scala/com/softwaremill/sttp/okhttp/monix/OkHttpMonixBackend.scala9
-rw-r--r--okhttp-backend/src/main/scala/com/softwaremill/sttp/okhttp/OkHttpClientHandler.scala36
13 files changed, 170 insertions, 88 deletions
diff --git a/README.md b/README.md
index 2429332..f998283 100644
--- a/README.md
+++ b/README.md
@@ -489,8 +489,9 @@ How to use:
import com.softwaremill.sttp._
import scala.concurrent.duration._
-// all backends provide a constructor that allows users to specify connection timeout
-implicit val backend = HttpURLConnectionBackend(connectionTimeout = 1.minute)
+// all backends provide a constructor that allows users to specify backend options
+implicit val backend = HttpURLConnectionBackend(
+ options = SttpBackendOptions.connectionTimeout(1.minute))
sttp
.get(uri"...")
@@ -498,6 +499,21 @@ sttp
.send()
```
+## Proxy
+
+A proxy can be specified when creating a backend:
+
+```scala
+import com.softwaremill.sttp._
+
+implicit val backend = HttpURLConnectionBackend(
+ options = SttpBackendOptions.httpProxy("some.host", 8080))
+
+sttp
+ .get(uri"...")
+ .send() // uses the proxy
+```
+
## SSL
SSL handling can be customized (or disabled) when creating a backend and is
diff --git a/akka-http-backend/src/main/scala/com/softwaremill/sttp/akkahttp/AkkaHttpBackend.scala b/akka-http-backend/src/main/scala/com/softwaremill/sttp/akkahttp/AkkaHttpBackend.scala
index 897692c..373c970 100644
--- a/akka-http-backend/src/main/scala/com/softwaremill/sttp/akkahttp/AkkaHttpBackend.scala
+++ b/akka-http-backend/src/main/scala/com/softwaremill/sttp/akkahttp/AkkaHttpBackend.scala
@@ -1,10 +1,11 @@
package com.softwaremill.sttp.akkahttp
import java.io.{File, IOException, UnsupportedEncodingException}
+import java.net.InetSocketAddress
import akka.actor.ActorSystem
import akka.event.LoggingAdapter
-import akka.http.scaladsl.{Http, HttpsConnectionContext}
+import akka.http.scaladsl.{ClientTransport, Http, HttpsConnectionContext}
import akka.http.scaladsl.coding.{Deflate, Gzip, NoCoding}
import akka.http.scaladsl.model.ContentTypes.`application/octet-stream`
import akka.http.scaladsl.model.HttpHeader.ParsingResult
@@ -30,7 +31,7 @@ class AkkaHttpBackend private (
actorSystem: ActorSystem,
ec: ExecutionContext,
terminateActorSystemOnClose: Boolean,
- connectionTimeout: FiniteDuration,
+ opts: SttpBackendOptions,
customHttpsContext: Option[HttpsConnectionContext],
customConnectionPoolSettings: Option[ConnectionPoolSettings],
customLog: Option[LoggingAdapter])
@@ -45,10 +46,17 @@ class AkkaHttpBackend private (
private val http = Http()
private val connectionSettings = ClientConnectionSettings(actorSystem)
- .withConnectingTimeout(connectionTimeout)
-
- private val connectionPoolSettings =
- customConnectionPoolSettings.getOrElse(ConnectionPoolSettings(actorSystem))
+ .withConnectingTimeout(opts.connectionTimeout)
+
+ private val connectionPoolSettings = {
+ val base = customConnectionPoolSettings.getOrElse(
+ ConnectionPoolSettings(actorSystem))
+ opts.proxy match {
+ case None => base
+ case Some(p) =>
+ base.withTransport(ClientTransport.httpsProxy(p.inetSocketAddress))
+ }
+ }
override def send[T](r: Request[T, S]): Future[Response[T]] = {
implicit val ec: ExecutionContext = this.ec
@@ -300,7 +308,7 @@ object AkkaHttpBackend {
actorSystem: ActorSystem,
ec: ExecutionContext,
terminateActorSystemOnClose: Boolean,
- connectionTimeout: FiniteDuration,
+ options: SttpBackendOptions,
customHttpsContext: Option[HttpsConnectionContext],
customConnectionPoolSettings: Option[ConnectionPoolSettings],
customLog: Option[LoggingAdapter])
@@ -309,7 +317,7 @@ object AkkaHttpBackend {
new AkkaHttpBackend(actorSystem,
ec,
terminateActorSystemOnClose,
- connectionTimeout,
+ options,
customHttpsContext,
customConnectionPoolSettings,
customLog))
@@ -319,8 +327,7 @@ object AkkaHttpBackend {
* e.g. mapping responses. Defaults to the global execution
* context.
*/
- def apply(connectionTimeout: FiniteDuration =
- SttpBackend.DefaultConnectionTimeout,
+ def apply(options: SttpBackendOptions = SttpBackendOptions.Default,
customHttpsContext: Option[HttpsConnectionContext] = None,
customConnectionPoolSettings: Option[ConnectionPoolSettings] = None,
customLog: Option[LoggingAdapter] = None)(
@@ -329,7 +336,7 @@ object AkkaHttpBackend {
AkkaHttpBackend(ActorSystem("sttp"),
ec,
terminateActorSystemOnClose = true,
- connectionTimeout,
+ options,
customHttpsContext,
customConnectionPoolSettings,
customLog)
@@ -343,7 +350,7 @@ object AkkaHttpBackend {
*/
def usingActorSystem(
actorSystem: ActorSystem,
- connectionTimeout: FiniteDuration = SttpBackend.DefaultConnectionTimeout,
+ options: SttpBackendOptions = SttpBackendOptions.Default,
customHttpsContext: Option[HttpsConnectionContext] = None,
customConnectionPoolSettings: Option[ConnectionPoolSettings] = None,
customLog: Option[LoggingAdapter] = None)(
@@ -352,7 +359,7 @@ object AkkaHttpBackend {
AkkaHttpBackend(actorSystem,
ec,
terminateActorSystemOnClose = false,
- connectionTimeout,
+ options,
customHttpsContext,
customConnectionPoolSettings,
customLog)
diff --git a/async-http-client-backend/cats/src/main/scala/com/softwaremill/sttp/asynchttpclient/cats/AsyncHttpClientCatsBackend.scala b/async-http-client-backend/cats/src/main/scala/com/softwaremill/sttp/asynchttpclient/cats/AsyncHttpClientCatsBackend.scala
index b5beb75..a38e08b 100644
--- a/async-http-client-backend/cats/src/main/scala/com/softwaremill/sttp/asynchttpclient/cats/AsyncHttpClientCatsBackend.scala
+++ b/async-http-client-backend/cats/src/main/scala/com/softwaremill/sttp/asynchttpclient/cats/AsyncHttpClientCatsBackend.scala
@@ -7,7 +7,8 @@ import com.softwaremill.sttp.asynchttpclient.AsyncHttpClientBackend
import com.softwaremill.sttp.{
FollowRedirectsBackend,
MonadAsyncError,
- SttpBackend
+ SttpBackend,
+ SttpBackendOptions
}
import org.asynchttpclient.{
AsyncHttpClient,
@@ -16,7 +17,6 @@ import org.asynchttpclient.{
}
import org.reactivestreams.Publisher
-import scala.concurrent.duration.FiniteDuration
import scala.language.higherKinds
class AsyncHttpClientCatsBackend[F[_]: Async] private (
@@ -48,11 +48,10 @@ object AsyncHttpClientCatsBackend {
new AsyncHttpClientCatsBackend(asyncHttpClient, closeClient))
def apply[F[_]: Async](
- connectionTimeout: FiniteDuration = SttpBackend.DefaultConnectionTimeout)
+ options: SttpBackendOptions = SttpBackendOptions.Default)
: SttpBackend[F, Nothing] =
- AsyncHttpClientCatsBackend(
- AsyncHttpClientBackend.defaultClient(connectionTimeout.toMillis.toInt),
- closeClient = true)
+ AsyncHttpClientCatsBackend(AsyncHttpClientBackend.defaultClient(options),
+ closeClient = true)
def usingConfig[F[_]: Async](
cfg: AsyncHttpClientConfig): SttpBackend[F, Nothing] =
diff --git a/async-http-client-backend/fs2/src/main/scala/com/softwaremill/sttp/asynchttpclient/fs2/AsyncHttpClientFs2Backend.scala b/async-http-client-backend/fs2/src/main/scala/com/softwaremill/sttp/asynchttpclient/fs2/AsyncHttpClientFs2Backend.scala
index 90db69c..4dfc1da 100644
--- a/async-http-client-backend/fs2/src/main/scala/com/softwaremill/sttp/asynchttpclient/fs2/AsyncHttpClientFs2Backend.scala
+++ b/async-http-client-backend/fs2/src/main/scala/com/softwaremill/sttp/asynchttpclient/fs2/AsyncHttpClientFs2Backend.scala
@@ -8,6 +8,7 @@ import com.softwaremill.sttp.{
FollowRedirectsBackend,
MonadAsyncError,
SttpBackend,
+ SttpBackendOptions,
Utf8,
concatByteBuffers
}
@@ -21,7 +22,6 @@ import org.asynchttpclient.{
import org.reactivestreams.Publisher
import scala.concurrent.ExecutionContext
-import scala.concurrent.duration.FiniteDuration
import scala.language.higherKinds
class AsyncHttpClientFs2Backend[F[_]: Effect] private (
@@ -64,13 +64,12 @@ object AsyncHttpClientFs2Backend {
* e.g. mapping responses. Defaults to the global execution
* context.
*/
- def apply[F[_]: Effect](connectionTimeout: FiniteDuration =
- SttpBackend.DefaultConnectionTimeout)(
+ def apply[F[_]: Effect](options: SttpBackendOptions =
+ SttpBackendOptions.Default)(
implicit ec: ExecutionContext = ExecutionContext.Implicits.global)
: SttpBackend[F, Stream[F, ByteBuffer]] =
- AsyncHttpClientFs2Backend[F](
- AsyncHttpClientBackend.defaultClient(connectionTimeout.toMillis.toInt),
- closeClient = true)
+ AsyncHttpClientFs2Backend[F](AsyncHttpClientBackend.defaultClient(options),
+ closeClient = true)
/**
* @param ec The execution context for running non-network related operations,
diff --git a/async-http-client-backend/future/src/main/scala/com/softwaremill/sttp/asynchttpclient/future/AsyncHttpClientFutureBackend.scala b/async-http-client-backend/future/src/main/scala/com/softwaremill/sttp/asynchttpclient/future/AsyncHttpClientFutureBackend.scala
index a46ed0d..6778fa0 100644
--- a/async-http-client-backend/future/src/main/scala/com/softwaremill/sttp/asynchttpclient/future/AsyncHttpClientFutureBackend.scala
+++ b/async-http-client-backend/future/src/main/scala/com/softwaremill/sttp/asynchttpclient/future/AsyncHttpClientFutureBackend.scala
@@ -3,7 +3,12 @@ package com.softwaremill.sttp.asynchttpclient.future
import java.nio.ByteBuffer
import com.softwaremill.sttp.asynchttpclient.AsyncHttpClientBackend
-import com.softwaremill.sttp.{FollowRedirectsBackend, FutureMonad, SttpBackend}
+import com.softwaremill.sttp.{
+ FollowRedirectsBackend,
+ FutureMonad,
+ SttpBackend,
+ SttpBackendOptions
+}
import org.asynchttpclient.{
AsyncHttpClient,
AsyncHttpClientConfig,
@@ -11,7 +16,6 @@ import org.asynchttpclient.{
}
import org.reactivestreams.Publisher
-import scala.concurrent.duration.FiniteDuration
import scala.concurrent.{ExecutionContext, Future}
class AsyncHttpClientFutureBackend private (
@@ -45,13 +49,11 @@ object AsyncHttpClientFutureBackend {
* e.g. mapping responses. Defaults to the global execution
* context.
*/
- def apply(connectionTimeout: FiniteDuration =
- SttpBackend.DefaultConnectionTimeout)(
+ def apply(options: SttpBackendOptions = SttpBackendOptions.Default)(
implicit ec: ExecutionContext = ExecutionContext.Implicits.global)
: SttpBackend[Future, Nothing] =
- AsyncHttpClientFutureBackend(
- AsyncHttpClientBackend.defaultClient(connectionTimeout.toMillis.toInt),
- closeClient = true)
+ AsyncHttpClientFutureBackend(AsyncHttpClientBackend.defaultClient(options),
+ closeClient = true)
/**
* @param ec The execution context for running non-network related operations,
diff --git a/async-http-client-backend/monix/src/main/scala/com/softwaremill/sttp/asynchttpclient/monix/AsyncHttpClientMonixBackend.scala b/async-http-client-backend/monix/src/main/scala/com/softwaremill/sttp/asynchttpclient/monix/AsyncHttpClientMonixBackend.scala
index c08c244..9cb44f2 100644
--- a/async-http-client-backend/monix/src/main/scala/com/softwaremill/sttp/asynchttpclient/monix/AsyncHttpClientMonixBackend.scala
+++ b/async-http-client-backend/monix/src/main/scala/com/softwaremill/sttp/asynchttpclient/monix/AsyncHttpClientMonixBackend.scala
@@ -6,6 +6,7 @@ import com.softwaremill.sttp.{
FollowRedirectsBackend,
MonadAsyncError,
SttpBackend,
+ SttpBackendOptions,
Utf8,
concatByteBuffers
}
@@ -20,7 +21,6 @@ import org.asynchttpclient.{
}
import org.reactivestreams.Publisher
-import scala.concurrent.duration.FiniteDuration
import scala.util.{Failure, Success}
class AsyncHttpClientMonixBackend private (
@@ -62,13 +62,11 @@ object AsyncHttpClientMonixBackend {
* @param s The scheduler used for streaming request bodies. Defaults to the
* global scheduler.
*/
- def apply(connectionTimeout: FiniteDuration =
- SttpBackend.DefaultConnectionTimeout)(
+ def apply(options: SttpBackendOptions = SttpBackendOptions.Default)(
implicit s: Scheduler = Scheduler.Implicits.global)
: SttpBackend[Task, Observable[ByteBuffer]] =
- AsyncHttpClientMonixBackend(
- AsyncHttpClientBackend.defaultClient(connectionTimeout.toMillis.toInt),
- closeClient = true)
+ AsyncHttpClientMonixBackend(AsyncHttpClientBackend.defaultClient(options),
+ closeClient = true)
/**
* @param s The scheduler used for streaming request bodies. Defaults to the
diff --git a/async-http-client-backend/scalaz/src/main/scala/com/softwaremill/sttp/asynchttpclient/scalaz/AsyncHttpClientScalazBackend.scala b/async-http-client-backend/scalaz/src/main/scala/com/softwaremill/sttp/asynchttpclient/scalaz/AsyncHttpClientScalazBackend.scala
index 12e217b..57e9577 100644
--- a/async-http-client-backend/scalaz/src/main/scala/com/softwaremill/sttp/asynchttpclient/scalaz/AsyncHttpClientScalazBackend.scala
+++ b/async-http-client-backend/scalaz/src/main/scala/com/softwaremill/sttp/asynchttpclient/scalaz/AsyncHttpClientScalazBackend.scala
@@ -5,7 +5,8 @@ import java.nio.ByteBuffer
import com.softwaremill.sttp.{
FollowRedirectsBackend,
MonadAsyncError,
- SttpBackend
+ SttpBackend,
+ SttpBackendOptions
}
import com.softwaremill.sttp.asynchttpclient.AsyncHttpClientBackend
import org.asynchttpclient.{
@@ -15,7 +16,6 @@ import org.asynchttpclient.{
}
import org.reactivestreams.Publisher
-import scala.concurrent.duration.FiniteDuration
import scalaz.{-\/, \/-}
import scalaz.concurrent.Task
@@ -43,12 +43,10 @@ object AsyncHttpClientScalazBackend {
new FollowRedirectsBackend[Task, Nothing](
new AsyncHttpClientScalazBackend(asyncHttpClient, closeClient))
- def apply(
- connectionTimeout: FiniteDuration = SttpBackend.DefaultConnectionTimeout)
+ def apply(options: SttpBackendOptions = SttpBackendOptions.Default)
: SttpBackend[Task, Nothing] =
- AsyncHttpClientScalazBackend(
- AsyncHttpClientBackend.defaultClient(connectionTimeout.toMillis.toInt),
- closeClient = true)
+ AsyncHttpClientScalazBackend(AsyncHttpClientBackend.defaultClient(options),
+ closeClient = true)
def usingConfig(cfg: AsyncHttpClientConfig): SttpBackend[Task, Nothing] =
AsyncHttpClientScalazBackend(new DefaultAsyncHttpClient(cfg),
diff --git a/async-http-client-backend/src/main/scala/com/softwaremill/sttp/asynchttpclient/AsyncHttpClientBackend.scala b/async-http-client-backend/src/main/scala/com/softwaremill/sttp/asynchttpclient/AsyncHttpClientBackend.scala
index 87a3965..a19dc1a 100644
--- a/async-http-client-backend/src/main/scala/com/softwaremill/sttp/asynchttpclient/AsyncHttpClientBackend.scala
+++ b/async-http-client-backend/src/main/scala/com/softwaremill/sttp/asynchttpclient/AsyncHttpClientBackend.scala
@@ -8,6 +8,7 @@ import com.softwaremill.sttp.ResponseAs.EagerResponseHandler
import com.softwaremill.sttp._
import org.asynchttpclient.AsyncHandler.State
import org.asynchttpclient.handler.StreamedAsyncHandler
+import org.asynchttpclient.proxy.ProxyServer
import org.asynchttpclient.request.body.multipart.{
ByteArrayPart,
FilePart,
@@ -17,8 +18,8 @@ import org.asynchttpclient.{
AsyncCompletionHandler,
AsyncHandler,
AsyncHttpClient,
- DefaultAsyncHttpClientConfig,
DefaultAsyncHttpClient,
+ DefaultAsyncHttpClientConfig,
HttpResponseBodyPart,
HttpResponseHeaders,
HttpResponseStatus,
@@ -298,12 +299,20 @@ abstract class AsyncHttpClientBackend[R[_], S](asyncHttpClient: AsyncHttpClient,
object AsyncHttpClientBackend {
private[asynchttpclient] def defaultClient(
- connectionTimeout: Int): AsyncHttpClient =
- new DefaultAsyncHttpClient(
- new DefaultAsyncHttpClientConfig.Builder()
- .setConnectTimeout(connectionTimeout)
- .build()
- )
+ options: SttpBackendOptions): AsyncHttpClient = {
+
+ var configBuilder = new DefaultAsyncHttpClientConfig.Builder()
+ .setConnectTimeout(options.connectionTimeout.toMillis.toInt)
+
+ configBuilder = options.proxy match {
+ case None => configBuilder
+ case Some(p) =>
+ configBuilder.setProxyServer(
+ new ProxyServer.Builder(p.host, p.port).build())
+ }
+
+ new DefaultAsyncHttpClient(configBuilder.build())
+ }
}
object EmptyPublisher extends Publisher[ByteBuffer] {
diff --git a/core/src/main/scala/com/softwaremill/sttp/HttpURLConnectionBackend.scala b/core/src/main/scala/com/softwaremill/sttp/HttpURLConnectionBackend.scala
index 7e87795..3d6921b 100644
--- a/core/src/main/scala/com/softwaremill/sttp/HttpURLConnectionBackend.scala
+++ b/core/src/main/scala/com/softwaremill/sttp/HttpURLConnectionBackend.scala
@@ -9,22 +9,21 @@ import java.util.concurrent.ThreadLocalRandom
import java.util.zip.{GZIPInputStream, InflaterInputStream}
import scala.annotation.tailrec
-import scala.io.Source
import scala.collection.JavaConverters._
-import scala.concurrent.duration.{Duration, FiniteDuration}
+import scala.concurrent.duration.Duration
+import scala.io.Source
class HttpURLConnectionBackend private (
- connectionTimeout: FiniteDuration,
+ opts: SttpBackendOptions,
customizeConnection: HttpURLConnection => Unit)
extends SttpBackend[Id, Nothing] {
override def send[T](r: Request[T, Nothing]): Response[T] = {
- val c =
- new URL(r.uri.toString).openConnection().asInstanceOf[HttpURLConnection]
+ val c = openConnection(r.uri)
c.setRequestMethod(r.method.m)
r.headers.foreach { case (k, v) => c.setRequestProperty(k, v) }
c.setDoInput(true)
c.setReadTimeout(timeout(r.options.readTimeout))
- c.setConnectTimeout(timeout(connectionTimeout))
+ c.setConnectTimeout(timeout(opts.connectionTimeout))
// redirects are handled by FollowRedirectsBackend
c.setInstanceFollowRedirects(false)
@@ -55,6 +54,17 @@ class HttpURLConnectionBackend private (
override def responseMonad: MonadError[Id] = IdMonad
+ private def openConnection(uri: Uri): HttpURLConnection = {
+ val url = new URL(uri.toString)
+ val conn = opts.proxy match {
+ case None => url.openConnection()
+ case Some(p) =>
+ url.openConnection(p.asJava)
+ }
+
+ conn.asInstanceOf[HttpURLConnection]
+ }
+
private def writeBody(body: RequestBody[Nothing],
c: HttpURLConnection): Option[OutputStream] = {
body match {
@@ -268,11 +278,10 @@ class HttpURLConnectionBackend private (
object HttpURLConnectionBackend {
- def apply(connectionTimeout: FiniteDuration =
- SttpBackend.DefaultConnectionTimeout,
+ def apply(options: SttpBackendOptions = SttpBackendOptions.Default,
customizeConnection: HttpURLConnection => Unit = { _ =>
()
}): SttpBackend[Id, Nothing] =
new FollowRedirectsBackend[Id, Nothing](
- new HttpURLConnectionBackend(connectionTimeout, customizeConnection))
+ new HttpURLConnectionBackend(options, customizeConnection))
}
diff --git a/core/src/main/scala/com/softwaremill/sttp/SttpBackend.scala b/core/src/main/scala/com/softwaremill/sttp/SttpBackend.scala
index 6eb312f..e3d5399 100644
--- a/core/src/main/scala/com/softwaremill/sttp/SttpBackend.scala
+++ b/core/src/main/scala/com/softwaremill/sttp/SttpBackend.scala
@@ -1,7 +1,6 @@
package com.softwaremill.sttp
import scala.language.higherKinds
-import scala.concurrent.duration._
/**
* @tparam R The type constructor in which responses are wrapped. E.g. `Id`
@@ -20,7 +19,3 @@ trait SttpBackend[R[_], -S] {
*/
def responseMonad: MonadError[R]
}
-
-object SttpBackend {
- private[sttp] val DefaultConnectionTimeout = 30.seconds
-}
diff --git a/core/src/main/scala/com/softwaremill/sttp/SttpBackendOptions.scala b/core/src/main/scala/com/softwaremill/sttp/SttpBackendOptions.scala
new file mode 100644
index 0000000..e515173
--- /dev/null
+++ b/core/src/main/scala/com/softwaremill/sttp/SttpBackendOptions.scala
@@ -0,0 +1,45 @@
+package com.softwaremill.sttp
+
+import java.net.InetSocketAddress
+
+import scala.concurrent.duration._
+import com.softwaremill.sttp.SttpBackendOptions._
+
+case class SttpBackendOptions(
+ connectionTimeout: FiniteDuration,
+ proxy: Option[Proxy]
+) {
+
+ def connectionTimeout(ct: FiniteDuration): SttpBackendOptions =
+ this.copy(connectionTimeout = ct)
+ def httpProxy(host: String, port: Int): SttpBackendOptions =
+ this.copy(proxy = Some(Proxy(host, port, ProxyType.Http)))
+ def socksProxy(host: String, port: Int): SttpBackendOptions =
+ this.copy(proxy = Some(Proxy(host, port, ProxyType.Socks)))
+}
+
+object SttpBackendOptions {
+ case class Proxy(host: String, port: Int, proxyType: ProxyType) {
+ def asJava = new java.net.Proxy(proxyType.asJava, inetSocketAddress)
+ def inetSocketAddress: InetSocketAddress =
+ InetSocketAddress.createUnresolved(host, port)
+ }
+
+ sealed trait ProxyType {
+ def asJava: java.net.Proxy.Type
+ }
+ object ProxyType {
+ case object Http extends ProxyType {
+ override def asJava: java.net.Proxy.Type = java.net.Proxy.Type.HTTP
+ }
+ case object Socks extends ProxyType {
+ override def asJava: java.net.Proxy.Type = java.net.Proxy.Type.SOCKS
+ }
+ }
+
+ val Default: SttpBackendOptions = SttpBackendOptions(30.seconds, None)
+
+ def connectionTimeout(ct: FiniteDuration): SttpBackendOptions = Default.connectionTimeout(ct)
+ def httpProxy(host: String, port: Int): SttpBackendOptions = Default.httpProxy(host, port)
+ def socksProxy(host: String, port: Int): SttpBackendOptions = Default.socksProxy(host, port)
+}
diff --git a/okhttp-backend/monix/src/main/scala/com/softwaremill/sttp/okhttp/monix/OkHttpMonixBackend.scala b/okhttp-backend/monix/src/main/scala/com/softwaremill/sttp/okhttp/monix/OkHttpMonixBackend.scala
index 4b24e65..db36f32 100644
--- a/okhttp-backend/monix/src/main/scala/com/softwaremill/sttp/okhttp/monix/OkHttpMonixBackend.scala
+++ b/okhttp-backend/monix/src/main/scala/com/softwaremill/sttp/okhttp/monix/OkHttpMonixBackend.scala
@@ -85,13 +85,12 @@ object OkHttpMonixBackend {
implicit s: Scheduler): SttpBackend[Task, Observable[ByteBuffer]] =
new FollowRedirectsBackend(new OkHttpMonixBackend(client, closeClient)(s))
- def apply(connectionTimeout: FiniteDuration =
- SttpBackend.DefaultConnectionTimeout)(
+ def apply(options: SttpBackendOptions = SttpBackendOptions.Default)(
implicit s: Scheduler = Scheduler.Implicits.global)
: SttpBackend[Task, Observable[ByteBuffer]] =
- OkHttpMonixBackend(OkHttpBackend.defaultClient(DefaultReadTimeout.toMillis,
- connectionTimeout.toMillis),
- closeClient = true)(s)
+ OkHttpMonixBackend(
+ OkHttpBackend.defaultClient(DefaultReadTimeout.toMillis, options),
+ closeClient = true)(s)
def usingClient(client: OkHttpClient)(implicit s: Scheduler =
Scheduler.Implicits.global)
diff --git a/okhttp-backend/src/main/scala/com/softwaremill/sttp/okhttp/OkHttpClientHandler.scala b/okhttp-backend/src/main/scala/com/softwaremill/sttp/okhttp/OkHttpClientHandler.scala
index 116878f..bebecac 100644
--- a/okhttp-backend/src/main/scala/com/softwaremill/sttp/okhttp/OkHttpClientHandler.scala
+++ b/okhttp-backend/src/main/scala/com/softwaremill/sttp/okhttp/OkHttpClientHandler.scala
@@ -148,14 +148,22 @@ abstract class OkHttpBackend[R[_], S](client: OkHttpClient,
object OkHttpBackend {
- private[okhttp] def defaultClient(readTimeout: Long,
- connectionTimeout: Long): OkHttpClient =
- new OkHttpClient.Builder()
+ private[okhttp] def defaultClient(
+ readTimeout: Long,
+ options: SttpBackendOptions): OkHttpClient = {
+ var clientBuilder = new OkHttpClient.Builder()
.followRedirects(false)
.followSslRedirects(false)
- .connectTimeout(connectionTimeout, TimeUnit.MILLISECONDS)
+ .connectTimeout(options.connectionTimeout.toMillis, TimeUnit.MILLISECONDS)
.readTimeout(readTimeout, TimeUnit.MILLISECONDS)
- .build()
+
+ clientBuilder = options.proxy match {
+ case None => clientBuilder
+ case Some(p) => clientBuilder.proxy(p.asJava)
+ }
+
+ clientBuilder.build()
+ }
private[okhttp] def updateClientIfCustomReadTimeout[T, S](
r: Request[T, S],
@@ -192,12 +200,11 @@ object OkHttpSyncBackend {
new FollowRedirectsBackend[Id, Nothing](
new OkHttpSyncBackend(client, closeClient))
- def apply(
- connectionTimeout: FiniteDuration = SttpBackend.DefaultConnectionTimeout)
+ def apply(options: SttpBackendOptions = SttpBackendOptions.Default)
: SttpBackend[Id, Nothing] =
- OkHttpSyncBackend(OkHttpBackend.defaultClient(DefaultReadTimeout.toMillis,
- connectionTimeout.toMillis),
- closeClient = true)
+ OkHttpSyncBackend(
+ OkHttpBackend.defaultClient(DefaultReadTimeout.toMillis, options),
+ closeClient = true)
def usingClient(client: OkHttpClient): SttpBackend[Id, Nothing] =
OkHttpSyncBackend(client, closeClient = false)
@@ -243,13 +250,12 @@ object OkHttpFutureBackend {
new FollowRedirectsBackend[Future, Nothing](
new OkHttpFutureBackend(client, closeClient))
- def apply(connectionTimeout: FiniteDuration =
- SttpBackend.DefaultConnectionTimeout)(
+ def apply(options: SttpBackendOptions = SttpBackendOptions.Default)(
implicit ec: ExecutionContext = ExecutionContext.Implicits.global)
: SttpBackend[Future, Nothing] =
- OkHttpFutureBackend(OkHttpBackend.defaultClient(DefaultReadTimeout.toMillis,
- connectionTimeout.toMillis),
- closeClient = true)
+ OkHttpFutureBackend(
+ OkHttpBackend.defaultClient(DefaultReadTimeout.toMillis, options),
+ closeClient = true)
def usingClient(client: OkHttpClient)(implicit ec: ExecutionContext =
ExecutionContext.Implicits.global)