Skip to content

Commit

Permalink
one place for all ignoreProxy cases except for asynhttpclient which h…
Browse files Browse the repository at this point in the history
…as inbuild proxy server
  • Loading branch information
nitsh committed Aug 15, 2018
1 parent f199bd1 commit 1f09d0b
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 21 deletions.
Expand Up @@ -48,8 +48,8 @@ class AkkaHttpBackend private (actorSystem: ActorSystem,
override def send[T](r: Request[T, S]): Future[Response[T]] = {
implicit val ec: ExecutionContext = this.ec

val connectionPoolSettingsWithProxy = opts.proxy match {
case Some(p) if !p.nonProxyHosts.contains(r.uri.host) =>
val connectionPoolSettingsWithProxy = opts.proxy match {
case Some(p) if !p.ignoreProxy(r.uri.host) =>
connectionPoolSettings.withTransport(ClientTransport.httpsProxy(p.inetSocketAddress))
case _ => connectionPoolSettings
}
Expand Down
Expand Up @@ -34,7 +34,7 @@ import scala.util.{Failure, Try}
abstract class AsyncHttpClientBackend[R[_], S](asyncHttpClient: AsyncHttpClient,
rm: MonadAsyncError[R],
closeClient: Boolean)
extends SttpBackend[R, S] {
extends SttpBackend[R, S] {

override def send[T](r: Request[T, S]): R[Response[T]] = {
val preparedRequest = asyncHttpClient
Expand Down Expand Up @@ -234,14 +234,14 @@ abstract class AsyncHttpClientBackend[R[_], S](asyncHttpClient: AsyncHttpClient,

private def readResponseNoBody(response: AsyncResponse): Response[Unit] = {
Response(Right(()),
response.getStatusCode,
response.getStatusText,
response.getHeaders
.iteratorAsString()
.asScala
.map(e => (e.getKey, e.getValue))
.toList,
Nil)
response.getStatusCode,
response.getStatusText,
response.getHeaders
.iteratorAsString()
.asScala
.map(e => (e.getKey, e.getValue))
.toList,
Nil)
}

private def eagerResponseHandler(response: AsyncResponse) =
Expand Down Expand Up @@ -289,7 +289,8 @@ object AsyncHttpClientBackend {
configBuilder = options.proxy match {
case None => configBuilder
case Some(p) =>
configBuilder.setProxyServer(new ProxyServer.Builder(p.host, p.port).setNonProxyHosts(p.nonProxyHosts.asJava).build())
configBuilder.setProxyServer(
new ProxyServer.Builder(p.host, p.port).setNonProxyHosts(p.nonProxyHosts.asJava).build())
}

new DefaultAsyncHttpClient(configBuilder.build())
Expand All @@ -300,4 +301,4 @@ object EmptyPublisher extends Publisher[ByteBuffer] {
override def subscribe(s: Subscriber[_ >: ByteBuffer]): Unit = {
s.onComplete()
}
}
}
Expand Up @@ -58,7 +58,7 @@ class HttpURLConnectionBackend private (opts: SttpBackendOptions, customizeConne
private def openConnection(uri: Uri): HttpURLConnection = {
val url = new URL(uri.toString)
val conn = opts.proxy match {
case Some(p) if !p.nonProxyHosts.exists(uri.host.startsWith) =>
case Some(p) if !p.ignoreProxy(uri.host) =>
url.openConnection(p.asJavaProxy)
case _ => url.openConnection()
}
Expand Down
@@ -1,7 +1,7 @@
package com.softwaremill.sttp

import java.io.IOException
import java.net.{InetSocketAddress, SocketAddress, URI}
import java.net.{InetSocketAddress, SocketAddress}
import java.{net, util}

import com.softwaremill.sttp.SttpBackendOptions._
Expand All @@ -24,19 +24,40 @@ case class SttpBackendOptions(

object SttpBackendOptions {
case class Proxy(host: String, port: Int, proxyType: ProxyType, nonProxyHosts: List[String] = Nil) {

//only matches prefix or suffix wild card(*)
private def isWildCardMatch(targetHost: String, nonProxyHost:String): Boolean = {
if (nonProxyHost.length > 1) {
if (nonProxyHost.charAt(0) == '*') {
targetHost.regionMatches(true, targetHost.length - nonProxyHost.length + 1, nonProxyHost, 1, nonProxyHost.length - 1)
}
else if (nonProxyHost.charAt(nonProxyHost.length - 1) == '*') {
targetHost.regionMatches(true, 0, nonProxyHost, 0, nonProxyHost.length - 1)
} else {
nonProxyHost.equalsIgnoreCase(targetHost)
}
} else {
nonProxyHost.equalsIgnoreCase(targetHost)
}
}

def ignoreProxy(host: String): Boolean = {
nonProxyHosts.exists(isWildCardMatch(host, _))
}

def asJavaProxySelector: net.ProxySelector = new net.ProxySelector {
override def select(uri: URI): util.List[net.Proxy] = {
override def select(uri: net.URI): util.List[net.Proxy] = {
val proxyList = new util.ArrayList[net.Proxy](1)
val uriHost = uri.getHost
if (uriHost.startsWith("127.0.0.1") || nonProxyHosts.forall(uriHost.startsWith)) {
if (ignoreProxy(uriHost)) {
proxyList.add(net.Proxy.NO_PROXY)
} else {
proxyList.add(asJavaProxy)
}
proxyList
}

override def connectFailed(uri: URI, sa: SocketAddress, ioe: IOException): Unit = {
override def connectFailed(uri: net.URI, sa: SocketAddress, ioe: IOException): Unit = {
throw new UnsupportedOperationException("Couldn't connect to the proxy server.")
}
}
Expand Down Expand Up @@ -77,9 +98,12 @@ object SttpBackendOptions {
def system(hostProp: String, portProp: String, nonProxyHostsPropOption: Option[String], make: (String, Int, List[String]) => Proxy, defaultPort: Int) = {
val host = Option(System.getProperty(hostProp))
def port = Try(System.getProperty(portProp).toInt).getOrElse(defaultPort)
def nonProxyHosts: List[String] = nonProxyHostsPropOption
.flatMap(nonProxyHostsProp => Try(System.getProperty(nonProxyHostsProp).split("|").toList).toOption)
.getOrElse(Nil)
def nonProxyHosts: List[String] = {
nonProxyHostsPropOption
.map(nonProxyHostsProp => Try(System.getProperty(nonProxyHostsProp)).toOption.getOrElse("localhost|127.*"))
.map(_.split("|").toList)
.getOrElse(Nil)
}
host.map(make(_, port, nonProxyHosts))
}

Expand Down
@@ -0,0 +1,50 @@
package com.softwaremill.sttp

import org.scalatest.{FlatSpec, Matchers}

class SttpBackendOptionsProxyTest extends FlatSpec with Matchers {

"ignoreProxy" should "return true for a exact match with nonProxyHosts" in {
val proxySetting = SttpBackendOptions.Proxy(
"fakeproxyserverhost", 8080,
SttpBackendOptions.ProxyType.Http,
List("a.nonproxy.host", "localhost", "127.*")
)

proxySetting.ignoreProxy("a.nonproxy.host") should be(true)
proxySetting.ignoreProxy("localhost") should be(true)
}

it should "return true for wildcard suffix match" in {
val proxySetting = SttpBackendOptions.Proxy(
"fakeproxyserverhost", 8080,
SttpBackendOptions.ProxyType.Http,
List("localhost", "127.*")
)

proxySetting.ignoreProxy("127.0.0.1") should be(true)
proxySetting.ignoreProxy("127.1.0.1") should be(true)
}

it should "return true for wildcard prefix match" in {
val proxySetting = SttpBackendOptions.Proxy(
"fakeproxyserverhost", 8080,
SttpBackendOptions.ProxyType.Http,
List("localhost", "*.local", "127.*")
)

proxySetting.ignoreProxy("sttp.local") should be(true)
proxySetting.ignoreProxy("www.sttp.local") should be(true)
}

it should "return false for others" in {
val proxySetting = SttpBackendOptions.Proxy(
"fakeproxyserverhost", 8080,
SttpBackendOptions.ProxyType.Http,
List("localhost", "*.local", "127.*")
)

proxySetting.ignoreProxy("sttp.local.com") should be(false)
proxySetting.ignoreProxy("10.127.0.1") should be(false)
}
}

0 comments on commit 1f09d0b

Please sign in to comment.