Last active
May 25, 2024 08:39
-
-
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/ee2be2e195c196c31f76b230df4f94928ac68ea
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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.14" | |
//> 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