Озвучивание SOAP-запросов в Scala

Я использую scalaxb для генерации моделей и клиентской части интерфейса SOAP. Для тестирования я использую Betamax, который также можно использовать в Scala. Тем не менее, scalaxb использует Netty в качестве транспорта, который игнорирует настройки прокси, установленные Betamax. Как бы вы справились с этой ситуацией?

scalaxb использует шаблон торта, поэтому сервис состоит из 3 частей, как в следующем примере:

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)

И тесты:

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()
      }
    }
  }
}

Версии:

  • 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. Финал

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)
    }
  }
}
Другие вопросы по тегам