Skip to content

Instantly share code, notes, and snippets.

@fancellu
Last active March 2, 2024 08:12
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fancellu/df6dde59249edf8401b28bbc44a78cbc to your computer and use it in GitHub Desktop.
Save fancellu/df6dde59249edf8401b28bbc44a78cbc to your computer and use it in GitHub Desktop.
Shows how to use okhttp and sttp in Scala asynchronously to talk to a Tor onion address via a Tor socks proxy, without trying to resolve DNS outside of proxy
// Shows how to use okhttp and sttp in Scala asynchronously to talk to a Tor onion address via a Tor socks proxy,
// without trying to resolve DNS outside of proxy (few http clients do this properly and instead return UnknownHostException)
// libraryDependencies ++= Seq("com.squareup.okhttp3" % "okhttp" % "4.7.2",
// "com.softwaremill.sttp.client" %% "okhttp-backend" % "2.1.2"))
import java.io.IOException
import java.net.{InetSocketAddress, Proxy}
import okhttp3.{Call, Callback, OkHttpClient, Request, Response}
import scala.concurrent.{Await, Future, Promise}
import scala.concurrent.duration._
import scala.util.Try
object OkScalaTorSocks extends App {
implicit val ec: scala.concurrent.ExecutionContext = scala.concurrent.ExecutionContext.global
// http client with a Socks proxy on localhost:9050
val client = new OkHttpClient.Builder().
proxy(new Proxy(Proxy.Type.SOCKS, new InetSocketAddress("127.0.0.1", 9050))).build
def getFuture(url: String): Future[Response] = {
val request = new Request.Builder().url(url).build
val promise = Promise[Response]
client.newCall(request).enqueue(new Callback() {
def onFailure(call: Call, e: IOException): Unit = promise.failure(e)
def onResponse(call: Call, response: Response): Unit = promise.success(response)
})
promise.future
}
val handle: Try[String] => Unit =
_.fold(
Console.err.println,
str => println(str)
)
val out = for {
response <- getFuture("http://expyuzz4wqqyqhjn.onion")
_ = println("Headers="+response.headers())
} yield response.body().string()
handle(Try {
"Result=" + Await.result(out, 10.seconds)
})
val badout = for {
response <- getFuture("http://expyuzz4wqqyqhjnxxxxx.onion")
} yield response.body().string()
handle(Try {
"Result=" + Await.result(badout, 10.seconds)
})
println("now for sttp")
implicit val sttpBackend = OkHttpSyncBackend.usingClient(client)
import sttp.client.quick._
val outSttp=quickRequest.get(uri"http://expyuzz4wqqyqhjn.onion").send()
println(outSttp)
client.dispatcher.executorService.shutdown()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment