2012-02-14 30 views
12

Tôi đang cố gắng sử dụng thư viện Finagle của Twitter để thực hiện một yêu cầu HTTP đến một máy chủ SOAP.Sử dụng Finagle cho máy khách Scala SOAP đơn giản

Mã bên dưới thực hiện thử nghiệm đầu tiên thành công (sử dụng java.net.URL), nhưng tôi đang gặp khó khăn với lần kiểm tra thứ hai (sử dụng ứng dụng khách Finagle). Tôi đang làm gì sai?

Ngoài ra, tôi tiếp tục bị lôi vào và bắt buộc bằng văn bản. Nếu bạn có thể giúp tôi làm cho Finagle bit hơn 'scala' như thế, tôi sẽ là vô cùng biết ơn.

đây đi:

import java.net.InetSocketAddress 
import scala.xml.{Elem, XML} 
import org.jboss.netty.buffer.ChannelBuffers 
import org.jboss.netty.util.CharsetUtil.UTF_8 
import com.twitter.finagle.Service; 
import com.twitter.finagle.builder.ClientBuilder; 
import com.twitter.finagle.http.Http; 
import org.jboss.netty.handler.codec.http._ 

class SoapClient { 
    private def error(msg: String) = { 
    println("SoapClient error: " + msg) 
    } 

    def wrap(xml: Elem): String = { 
    val buf = new StringBuilder 
    buf.append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone= 
\"no\"?>\n") 
    buf.append("<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http:// 
schemas.xmlsoap.org/soap/envelope/\">\n") 
    buf.append("<SOAP-ENV:Body>\n") 
    buf.append(xml.toString) 
    buf.append("\n</SOAP-ENV:Body>\n") 
    buf.append("</SOAP-ENV:Envelope>\n") 
    buf.toString 
    } 

    def sendWithJavaNetURL(host: String, req: Elem): Option[Elem] = { 
    val url = new java.net.URL(host) 
    val outs = wrap(req).getBytes 
    val conn = 
url.openConnection.asInstanceOf[java.net.HttpURLConnection] 
    try { 
     conn.setRequestMethod("POST") 
     conn.setDoOutput(true) 
     conn.setRequestProperty("Content-Length", outs.length.toString) 
     conn.setRequestProperty("Content-Type", "text/xml") 
     conn.getOutputStream.write(outs) 
     conn.getOutputStream.close 
     Some(XML.load(conn.getInputStream)) 
    } 
    catch { 
     case e: Exception => error("post: " + e) 
     error("post:" + 
scala.io.Source.fromInputStream(conn.getErrorStream).mkString) 
     None 
    } 
    } 

    def sendWithFinagle(host: String, path: String, req: Elem) = { 
    val clientService: Service[HttpRequest, HttpResponse] = 
ClientBuilder() 
     .codec(Http()) 
     .hosts(new InetSocketAddress(host, 80)) 
     .hostConnectionLimit(1) 
     .build() 
    val request: HttpRequest = new 
DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, "/") 
    val soapPacket: String = wrap(req) 
    request.setContent(ChannelBuffers.copiedBuffer(soapPacket, UTF_8)) 
    request.setHeader("Content-Lenght", soapPacket.length()) 
    request.setHeader("Content-Type", "text/xml") 
    request.setUri("path") 
    val client = clientService(request) 
    val response = client.get() 
    println(response) 
    } 
} 

object SoapTest { 

    def testWithJavaNetURL { 
    val host = "https://apitest.authorize.net/soap/v1/Service.asmx" 
    val req = <IsAlive xmlns="https://api.authorize.net/soap/v1/"/> 
    val cli = new SoapClient 
    println("##### Test with Java Net URL: request:\n" + 
cli.wrap(req)) 
    val resp = cli.sendWithJavaNetURL(host, req) 
    if (resp.isDefined) { 
     println("##### response:\n" + resp.get.toString) 
    } 
    } 

    def testWithFinagle { 
    val host = "apitest.authorize.net" 
    val path = "/soap/v1/Service.asmx" 
    val req = <IsAlive xmlns="https://api.authorize.net/soap/v1/"/> 
    val cli = new SoapClient 
    println("##### Test with Finagle: request:\n" + cli.wrap(req)) 
    cli.sendWithFinagle(host, path, req) 
    } 

    def main(args: Array[String]) { 
    testWithJavaNetURL 
    testWithFinagle 
    } 

Trả lời

13

Jean-Phillippe, từ Finagles forum, vui lòng cung cấp một answer on github

Dưới đây là toàn bộ hoạt động và mã cập nhật độc đáo:

import java.net.InetSocketAddress 
import scala.xml.{Elem, XML} 
import org.jboss.netty.buffer.ChannelBuffers 
import org.jboss.netty.util.CharsetUtil.UTF_8 
import com.twitter.finagle.Service; 
import com.twitter.finagle.builder.ClientBuilder; 
import com.twitter.finagle.http.{Http, RequestBuilder}; 
import org.jboss.netty.handler.codec.http._ 
import org.jboss.netty.buffer.ChannelBuffers.wrappedBuffer 
import java.net.URL 
class SoapClient { 
    private def error(msg: String) = { 
    println("SoapClient error: " + msg) 
    } 
    def wrap(xml: Elem): String = { 
    val wrapper = <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> 
       <SOAP-ENV:Body> 
        {xml} 
       </SOAP-ENV:Body> 
       </SOAP-ENV:Envelope> 
    wrapper.toString 
    } 
    def sendWithJavaNetURL(host: String, req: Elem): Option[Elem] = { 
    val url = new java.net.URL(host) 
    val outs = wrap(req).getBytes 
    val conn = 
url.openConnection.asInstanceOf[java.net.HttpURLConnection] 
    try { 
     conn.setRequestMethod("POST") 
     conn.setDoOutput(true) 
     conn.setRequestProperty("Content-Length", outs.length.toString) 
     conn.setRequestProperty("Content-Type", "text/xml") 
     conn.getOutputStream.write(outs) 
     conn.getOutputStream.close 
     Some(XML.load(conn.getInputStream)) 
    } 
    catch { 
     case e: Exception => error("post: " + e) 
     error("post:" + 
scala.io.Source.fromInputStream(conn.getErrorStream).mkString) 
     None 
    } 
    } 
    def sendWithFinagle(host: String, path: String, req: Elem) = { 
    val clientService: Service[HttpRequest, HttpResponse] = 
ClientBuilder() 
     .codec(Http()) 
     .hosts(new InetSocketAddress(host, 443)) 
     .tls(host) 
     .hostConnectionLimit(1) 
     .build() 
    val payload = wrap(req).getBytes("UTF-8") 
    val request: HttpRequest = RequestBuilder().url(new URL("https", host, 443, path)) 
               .setHeader("Content-Type", "text/xml") 
               .setHeader("Content-Length", payload.length.toString) 
               .buildPost(wrappedBuffer(payload)) 

    val client = clientService(request) 

    for(response <- client) { 
     println(response) 
     println(response.getContent.toString("UTF-8")) 
    } 
    // val response = client.get() 
    } 
} 

object SoapTest { 
    def testWithJavaNetURL { 
    val host = "https://apitest.authorize.net/soap/v1/Service.asmx" 
    val req = <IsAlive xmlns="https://api.authorize.net/soap/v1/"/> 
    val cli = new SoapClient 
    println("##### Test with Java Net URL: request:\n" + 
cli.wrap(req)) 
    val resp = cli.sendWithJavaNetURL(host, req) 
    if (resp.isDefined) { 
     println("##### response:\n" + resp.get.toString) 
    } 
    } 
    def testWithFinagle { 
    val host = "apitest.authorize.net" 
    val path = "/soap/v1/Service.asmx" 
    val req = <IsAlive xmlns="https://api.authorize.net/soap/v1/"/> 
    val cli = new SoapClient 
    println("##### Test with Finagle: request:\n" + cli.wrap(req)) 
    cli.sendWithFinagle(host, path, req) 
    } 
    def main(args: Array[String]) { 
    testWithJavaNetURL 
    testWithFinagle 
    } 
} 

SoapTest.main(Array[String]()) 
Các vấn đề liên quan