2015-07-19 66 views
2

我正在使用Scala和Akka构建电信公司的应用程序,并且需要使用UCIP protocol与帐户信息和重填服务器进行通信。如何使用喷雾客户端设置非标准用户代理?

UCIP是一个简单的协议,建立在XMLRPC上;我遇到的唯一问题是它需要客户端以User-Agent: <client name>/<protocol version>/<client version>的特定格式设置User-Agent标题,该标题将喷出的分析视为无效。

我试图创建一个自定义User-Agent标题,从spray.http.HttpHeader继承,但它仍然无法正常工作。下面是我到目前为止有:

import akka.actor.ActorSystem 
import akka.event.{Logging, LoggingAdapter} 
import spray.client.pipelining._ 
import spray.http._ 
import spray.httpx._ 

case class `User-Agent`(value: String) extends HttpHeader { 
    def lowercaseName: String = "user-agent" 
    def name: String = "User-Agent" 
    def render[R <: Rendering](r: R): r.type = r ~~ s"User-Agent: $value" 
} 

class UcipClient(val url: String, val protocol: String, username: String, password: String) (implicit system: ActorSystem) { 

    val log = Logging.getLogger(system, this) 
    val logRequest: HttpRequest => HttpRequest = { r => log.debug(r.toString); r } 
    val logResponse: HttpResponse => HttpResponse = { r => log.debug(r.toString); r } 

    val pipeline = (
     addHeader(`User-Agent`("USSD-UCIP/%s/1.0".format(protocol))) 
     ~> addCredentials(BasicHttpCredentials(username, password)) 
     ~> logRequest 
     ~> sendReceive 
     ~> logResponse 
    ) 

    def send(req: UcipRequest) = pipeline(Post(url, req.getRequest)) 
} 

我的请求回头率“对不起,发生错误:403,无效的协议版本没有定义”,但是,他们回到正确的反应,当我发送邮件使用curl相同的细节。

我错过了什么,甚至可以用喷客户端?我花了一些时间检查互联网(这导致我走向自定义标题路线),但仍然没有想出这个......真的很感谢任何帮助:-)

回答

2

原来我wasn离答案还很远。在检查通过网络发送的头文件时,我注意到User-Agent被设置了两次:一次是我的代码,另一次是Spray(因为它认为我的头文件无效)。

spray.can.client.user-agent-header设置为空字符串""删除了第二个标头,并且请求成功。这里的自定义标题的最终版本:

import spray.http._ 

object CustomHttpHeaders { 
    case class `User-Agent`(val value: String) extends HttpHeader with Product with Serializable { 
     def lowercaseName: String = "user-agent" 
     def name: String = "User-Agent" 
     def render[R <: Rendering](r: R): r.type = r ~~ s"User-Agent: $value" 
    } 
} 

和最终客户UCIP:

import akka.actor.ActorRefFactory 
import com.typesafe.config.Config 
import scala.concurrent.ExecutionContext.Implicits.global 
import scala.xml.NodeSeq 
import spray.client.pipelining._ 
import spray.http._ 
import spray.httpx._ 

class UcipFault(val code: Int, msg: String) extends RuntimeException(s"$code: $msg") 

class AirException(val code: Int) extends RuntimeException(s"$code") 

class UcipClient(config: Config, val url: String)(implicit context: ActorRefFactory) { 
    import CustomHttpHeaders._ 

    val throwOnFailure: NodeSeq => NodeSeq = { 
     case f if (f \\ "fault").size != 0 => 
      val faultData = (f \\ "fault" \\ "member" \ "value") 
      throw new UcipFault((faultData \\ "i4").text.toInt, 
           (faultData \\ "string").text) 
     case el => 
      val responseCode = ((el \\ "member") 
       .filter { n => (n \\ "name").text == "responseCode" } 
       .map { n => (n \\ "i4").text.toInt }).head 
      if (responseCode == 0) el else throw new AirException(responseCode) 
    } 

    val pipeline = (
     addHeader(`User-Agent`("USSD-UCIP/%s/1.0".format(config.getString("ucip.server-protocol")))) 
     ~> addCredentials(BasicHttpCredentials(config.getString("ucip.server-username"), config.getString("ucip.server-password"))) 
     ~> sendReceive 
     ~> unmarshal[NodeSeq] 
     ~> throwOnFailure 
    ) 

    def send(req: UcipRequest) = pipeline(Post(url, req.getRequest)) 
} 
相关问题