2

I use scalaxb to generate models and client part of the SOAP interface. For testing I use Betamax, which can also be used in Scala. However, scalaxb uses Netty as a transport, which ignores proxy settings set up by Betamax. How would you cope with this situation?

scalaxb uses cake pattern, so the service is built from 3 parts like in the following example:

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent._
import scala.concurrent.duration._

val service = (new stockquote.StockQuoteSoap12Bindings with
  scalaxb.SoapClientsAsync with
  scalaxb.DispatchHttpClientsAsync {}).service
val fresponse = service.getQuote(Some("GOOG"))
val response = Await.result(fresponse, 5 seconds)
println(response)

And tests:

import co.freeside.betamax.{TapeMode, Recorder}
import co.freeside.betamax.proxy.jetty.ProxyServer
import dispatch._
import org.scalatest.{Tag, FunSuite}
import scala.concurrent.duration._

import scala.concurrent.{Await, Future}

class StockquoteSpec extends FunSuite with Betamax {

  testWithBetamax("stockquote", Some(TapeMode.READ_WRITE))("stockquote") { 
    val fresponse = service.getQuote(Some("GOOG"))
    val response = Await.result(fresponse, 5 seconds)
    println(response)
  }
}

trait Betamax {

  protected def test(testName: String, testTags: Tag*)(testFun: => Unit)

  def testWithBetamax(tape: String, mode: Option[TapeMode] = None)(testName: String, testTags: Tag*)(testFun: => Unit) = {
    test(testName, testTags: _*) {
      val recorder = new Recorder
      val proxyServer = new ProxyServer(recorder)
      recorder.insertTape(tape)
      recorder.getTape.setMode(mode.getOrElse(recorder.getDefaultMode()))
      proxyServer.start()
      try {
        testFun
      } finally {
        recorder.ejectTape()
        proxyServer.stop()
      }
    }
  }
}

Versions:

  • net.databinder.dispatch 0.11.2
  • co.freeside.betamax 1.1.2
  • com.ning.async-http-client 1.8.10
  • io.netty.netty 3.9.2.Final
4

1 回答 1

1

确实可以在 Netty 中使用代理。尽管 Netty 不读取代理设置的系统属性,但可以使用ProxyServerSelector. 它是在以下build方法中创建的AsyncHttpClientConfig

if (proxyServerSelector == null && useProxySelector) {
    proxyServerSelector = ProxyUtils.getJdkDefaultProxyServerSelector();
}

if (proxyServerSelector == null && useProxyProperties) {
    proxyServerSelector = ProxyUtils.createProxyServerSelector(System.getProperties());
}

if (proxyServerSelector == null) {
    proxyServerSelector = ProxyServerSelector.NO_PROXY_SELECTOR;
}

唯一的障碍是scalaxb使用默认配置和useProxyProperties=false. MyDispatchHttpClientsAsync您可以使用创建服务时可以使用的自定义覆盖它:

val service = (new stockquote.StockQuoteSoap12Bindings with
  scalaxb.SoapClientsAsync with
  MyDispatchHttpClientsAsync {}).service

MyDispatchHttpClientsAsync以及(重点是调用)的源码setUseProxyProperties(true)

import com.ning.http.client.providers.netty.NettyAsyncHttpProvider
import com.ning.http.client.{AsyncHttpClientConfig, AsyncHttpClient}
import scalaxb.HttpClientsAsync

/**
 * @author miso
 */
trait MyDispatchHttpClientsAsync extends HttpClientsAsync {
  lazy val httpClient = new DispatchHttpClient {}

  trait DispatchHttpClient extends HttpClient {
    import dispatch._, Defaults._

    // Keep it lazy. See https://github.com/eed3si9n/scalaxb/pull/279
    lazy val http = new Http(new AsyncHttpClient(new NettyAsyncHttpProvider(new AsyncHttpClientConfig.Builder().setUseProxyProperties(true).build())))
//    lazy val http = Http.configure(_.setUseProxyProperties(true)) // Maybe later. See https://github.com/eed3si9n/scalaxb/issues/312

    def request(in: String, address: java.net.URI, headers: Map[String, String]): concurrent.Future[String] = {
      val req = url(address.toString).setBodyEncoding("UTF-8") <:< headers << in
      http(req > as.String)
    }
  }
}
于 2015-03-11T15:31:01.577 回答