Skip to content

Instantly share code, notes, and snippets.

@dacr
Last active June 25, 2023 15:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dacr/93fcd2cb806bbd1c24a48e7148aa12c8 to your computer and use it in GitHub Desktop.
Save dacr/93fcd2cb806bbd1c24a48e7148aa12c8 to your computer and use it in GitHub Desktop.
Fully asynchronous http client call using akka-http will work in all cases, even with chunked responses, this example add automatic http proxy support. / published by https://github.com/dacr/code-examples-manager #fd5460d1-72a2-4748-906c-a81c57cd5024/6bd12ab37d56476c4377e8e2a05badfbcb5b9227
// summary : Fully asynchronous http client call using akka-http will work in all cases, even with chunked responses, this example add automatic http proxy support.
// keywords : scala, actors, akka, http-client, client, http-proxy
// publish : gist
// authors : David Crosson
// license : Apache NON-AI License Version 2.0 (https://raw.githubusercontent.com/non-ai-licenses/non-ai-licenses/main/NON-AI-APACHE2)
// id : fd5460d1-72a2-4748-906c-a81c57cd5024
// created-on : 2018-06-19T19:10:04Z
// managed-by : https://github.com/dacr/code-examples-manager
// run-with : scala-cli $file
// ---------------------
//> using scala "2.13.8"
//> using dep "com.typesafe.akka::akka-http:10.2.7"
//> using dep "com.typesafe.akka::akka-stream:2.6.18"
// ---------------------
/*
Fully asynchronous http client call using akka-http with automatic http proxy support
scala in script mode using ammonite REPL (http://ammonite.io/)
*/
import akka.http.scaladsl._
import akka.http.scaladsl.model._
import akka.http.scaladsl.unmarshalling.Unmarshal
import akka.http.scaladsl.settings.{ClientConnectionSettings, ConnectionPoolSettings}
import java.net.InetSocketAddress
import scala.util.{Failure, Success}
import scala.util.Properties.{envOrNone, propOrNone}
import scala.concurrent._
import scala.concurrent.duration._
case class HttpProxyConfig(host:String, port:Int)
object HttpProxyConfig {
def fromPropOrEnv():Option[HttpProxyConfig] = {
val key = "http_proxy"
propOrNone(key).orElse(envOrNone(key)).flatMap(fromProvidedString)
}
def fromProvidedString(spec:String):Option[HttpProxyConfig] = {
val extractor = """^http://([^:/]+)(?::(\d+))?/?$""".r
extractor.findFirstIn(spec.trim.toLowerCase()).collect {
case extractor(host,null) => HttpProxyConfig(host, 80)
case extractor(host,port) => HttpProxyConfig(host, port.toInt)
}
}
}
object TestThat {
implicit val system = akka.actor.ActorSystem("ClientSystem")
implicit val executionContext = system.dispatcher
private val transport =
HttpProxyConfig.fromPropOrEnv().collect {
case proxy@HttpProxyConfig(proxyHost, proxyPort) =>
println(s"using proxy $proxy")
ClientTransport.httpsProxy(InetSocketAddress.createUnresolved(proxyHost, proxyPort))
}
private val settings =
ClientConnectionSettings(system)
.withTransport(transport.getOrElse(ClientTransport.TCP))
.withIdleTimeout(10.seconds)
.withConnectingTimeout(5.seconds)
private val poolSettings =
ConnectionPoolSettings(system)
.withConnectionSettings(settings)
.withMaxConnections(10)
.withMaxRetries(1)
val uri = "http://www.chezmoicamarche.fr"
val futureResponse = Http().singleRequest(HttpRequest(uri = uri), settings=poolSettings)
val futureResult = futureResponse.transformWith{
case Success(response) => Unmarshal(response.entity).to[String]
case Failure(ex) =>
ex.printStackTrace()
throw ex
}
val lastFuture = futureResult.map(println).andThen(_ => system.terminate())
// Do not exit before the future has completed ;)
def andWait():Unit = Await.ready(lastFuture, 5.seconds)
}
TestThat.andWait()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment