2015-07-19 79 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)) 
} 
相關問題