aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md16
-rw-r--r--akka-http-backend/src/main/scala/com/softwaremill/sttp/akkahttp/AkkaHttpBackend.scala70
-rw-r--r--core/src/main/scala/com/softwaremill/sttp/HttpURLConnectionBackend.scala16
3 files changed, 78 insertions, 24 deletions
diff --git a/README.md b/README.md
index 725f758..c12b4e7 100644
--- a/README.md
+++ b/README.md
@@ -498,6 +498,22 @@ sttp
.send()
```
+## SSL
+
+SSL handling can be customized (or disabled) when creating a backend and is
+backend-specific.
+
+Depending on the underlying backend's client, you can customize SSL settings
+as follows:
+
+* `HttpUrlConnectionBackend`: when creating the backend, specify the `customizeConnection: HttpURLConnection => Unit`
+parameter, and set the hostname verifier & SSL socket factory as required
+* akka-http: when creating the backend, specify the `customHttpsContext: Option[HttpsConnectionContext]`
+parameter. See [akka-http docs](http://doc.akka.io/docs/akka-http/current/scala/http/server-side/server-https-support.html)
+* async-http-client: create a custom client and use the `setSSLContext` method
+* OkHttp: create a custom client modifying the SSL settings as described
+[on the wiki](https://github.com/square/okhttp/wiki/HTTPS)
+
## Notes
* the encoding for `String`s defaults to `utf-8`.
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 57b5441..897692c 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
@@ -3,7 +3,8 @@ package com.softwaremill.sttp.akkahttp
import java.io.{File, IOException, UnsupportedEncodingException}
import akka.actor.ActorSystem
-import akka.http.scaladsl.Http
+import akka.event.LoggingAdapter
+import akka.http.scaladsl.{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
@@ -25,10 +26,14 @@ import scala.concurrent.duration.FiniteDuration
import scala.concurrent.{ExecutionContext, Future}
import scala.util.{Failure, Success, Try}
-class AkkaHttpBackend private (actorSystem: ActorSystem,
- ec: ExecutionContext,
- terminateActorSystemOnClose: Boolean,
- connectionTimeout: FiniteDuration)
+class AkkaHttpBackend private (
+ actorSystem: ActorSystem,
+ ec: ExecutionContext,
+ terminateActorSystemOnClose: Boolean,
+ connectionTimeout: FiniteDuration,
+ customHttpsContext: Option[HttpsConnectionContext],
+ customConnectionPoolSettings: Option[ConnectionPoolSettings],
+ customLog: Option[LoggingAdapter])
extends SttpBackend[Future, Source[ByteString, Any]] {
// the supported stream type
@@ -37,10 +42,13 @@ class AkkaHttpBackend private (actorSystem: ActorSystem,
private implicit val as: ActorSystem = actorSystem
private implicit val materializer: ActorMaterializer = ActorMaterializer()
+ private val http = Http()
+
private val connectionSettings = ClientConnectionSettings(actorSystem)
.withConnectingTimeout(connectionTimeout)
- private val connectionPoolSettings = ConnectionPoolSettings(actorSystem)
+ private val connectionPoolSettings =
+ customConnectionPoolSettings.getOrElse(ConnectionPoolSettings(actorSystem))
override def send[T](r: Request[T, S]): Future[Response[T]] = {
implicit val ec: ExecutionContext = this.ec
@@ -52,7 +60,13 @@ class AkkaHttpBackend private (actorSystem: ActorSystem,
requestToAkka(r)
.flatMap(setBodyOnAkka(r, r.body, _))
.toFuture
- .flatMap(req => Http().singleRequest(req, settings = settings))
+ .flatMap(
+ req =>
+ http.singleRequest(req,
+ settings = settings,
+ connectionContext = customHttpsContext.getOrElse(
+ http.defaultClientHttpsContext),
+ log = customLog.getOrElse(actorSystem.log)))
.flatMap { hr =>
val code = hr.status.intValue()
@@ -282,17 +296,23 @@ class AkkaHttpBackend private (actorSystem: ActorSystem,
}
object AkkaHttpBackend {
-
- private def apply(actorSystem: ActorSystem,
- ec: ExecutionContext,
- terminateActorSystemOnClose: Boolean,
- connectionTimeout: FiniteDuration)
+ private def apply(
+ actorSystem: ActorSystem,
+ ec: ExecutionContext,
+ terminateActorSystemOnClose: Boolean,
+ connectionTimeout: FiniteDuration,
+ customHttpsContext: Option[HttpsConnectionContext],
+ customConnectionPoolSettings: Option[ConnectionPoolSettings],
+ customLog: Option[LoggingAdapter])
: SttpBackend[Future, Source[ByteString, Any]] =
new FollowRedirectsBackend(
new AkkaHttpBackend(actorSystem,
ec,
terminateActorSystemOnClose,
- connectionTimeout))
+ connectionTimeout,
+ customHttpsContext,
+ customConnectionPoolSettings,
+ customLog))
/**
* @param ec The execution context for running non-network related operations,
@@ -300,13 +320,19 @@ object AkkaHttpBackend {
* context.
*/
def apply(connectionTimeout: FiniteDuration =
- SttpBackend.DefaultConnectionTimeout)(
+ SttpBackend.DefaultConnectionTimeout,
+ customHttpsContext: Option[HttpsConnectionContext] = None,
+ customConnectionPoolSettings: Option[ConnectionPoolSettings] = None,
+ customLog: Option[LoggingAdapter] = None)(
implicit ec: ExecutionContext = ExecutionContext.Implicits.global)
: SttpBackend[Future, Source[ByteString, Any]] =
AkkaHttpBackend(ActorSystem("sttp"),
ec,
terminateActorSystemOnClose = true,
- connectionTimeout)
+ connectionTimeout,
+ customHttpsContext,
+ customConnectionPoolSettings,
+ customLog)
/**
* @param actorSystem The actor system which will be used for the http-client
@@ -315,13 +341,19 @@ object AkkaHttpBackend {
* e.g. mapping responses. Defaults to the global execution
* context.
*/
- def usingActorSystem(actorSystem: ActorSystem,
- connectionTimeout: FiniteDuration =
- SttpBackend.DefaultConnectionTimeout)(
+ def usingActorSystem(
+ actorSystem: ActorSystem,
+ connectionTimeout: FiniteDuration = SttpBackend.DefaultConnectionTimeout,
+ customHttpsContext: Option[HttpsConnectionContext] = None,
+ customConnectionPoolSettings: Option[ConnectionPoolSettings] = None,
+ customLog: Option[LoggingAdapter] = None)(
implicit ec: ExecutionContext = ExecutionContext.Implicits.global)
: SttpBackend[Future, Source[ByteString, Any]] =
AkkaHttpBackend(actorSystem,
ec,
terminateActorSystemOnClose = false,
- connectionTimeout)
+ connectionTimeout,
+ customHttpsContext,
+ customConnectionPoolSettings,
+ customLog)
}
diff --git a/core/src/main/scala/com/softwaremill/sttp/HttpURLConnectionBackend.scala b/core/src/main/scala/com/softwaremill/sttp/HttpURLConnectionBackend.scala
index 2dbb13d..62ef2bc 100644
--- a/core/src/main/scala/com/softwaremill/sttp/HttpURLConnectionBackend.scala
+++ b/core/src/main/scala/com/softwaremill/sttp/HttpURLConnectionBackend.scala
@@ -13,7 +13,9 @@ import scala.io.Source
import scala.collection.JavaConverters._
import scala.concurrent.duration.{Duration, FiniteDuration}
-class HttpURLConnectionBackend private (connectionTimeout: FiniteDuration)
+class HttpURLConnectionBackend private (
+ connectionTimeout: FiniteDuration,
+ customizeConnection: HttpURLConnection => Unit)
extends SttpBackend[Id, Nothing] {
override def send[T](r: Request[T, Nothing]): Response[T] = {
val c =
@@ -27,6 +29,8 @@ class HttpURLConnectionBackend private (connectionTimeout: FiniteDuration)
// redirects are handled by FollowRedirectsBackend
c.setInstanceFollowRedirects(false)
+ customizeConnection(c)
+
if (r.body != NoBody) {
c.setDoOutput(true)
// we need to take care to:
@@ -258,9 +262,11 @@ class HttpURLConnectionBackend private (connectionTimeout: FiniteDuration)
object HttpURLConnectionBackend {
- def apply(
- connectionTimeout: FiniteDuration = SttpBackend.DefaultConnectionTimeout)
- : SttpBackend[Id, Nothing] =
+ def apply(connectionTimeout: FiniteDuration =
+ SttpBackend.DefaultConnectionTimeout,
+ customizeConnection: HttpURLConnection => Unit = { _ =>
+ ()
+ }): SttpBackend[Id, Nothing] =
new FollowRedirectsBackend[Id, Nothing](
- new HttpURLConnectionBackend(connectionTimeout))
+ new HttpURLConnectionBackend(connectionTimeout, customizeConnection))
}