2014-03-26 57 views
4

和訊訪問RDIO OAuth的API,當我嘗試使用Scala的調度訪問RDIO API這樣的:錯誤階

import dispatch.url 
import dispatch.Http 
import dispatch.Defaults.executor 
import dispatch._ 
import com.ning.http.client.oauth.ConsumerKey 
import dispatch.oauth._ 

val consumer = new ConsumerKey("my key", "my secret") 
val params = Map("method" -> "get", "keys" -> id, "extras" -> "-*,playCount") 
val request = url("http://api.rdio.com/1/").POST <@ consumer << params <:< Map("Accept" -> "application/json") 
val response = Http(request OK as.String) 

我得到一個錯誤403

有什麼不對?我相信我的鑰匙是正確的。

+0

不熟悉斯卡拉,但我在Rdio工作。你是否將這些參數傳遞給POST請求的主體或查詢字符串中?請求的正文是正確的。還建議通過Authorization標頭傳遞OAuth憑證。 –

+0

是的,「參數確實是這樣的:向POST主體添加參數。身份驗證標頭應該通過添加<@方法與密鑰 –

+0

您使用哪個版本的調度? – alcarv

回答

1

我分析了rdio頁面上的python示例與Scala所做的不同之處。

我覺得真的有兩個問題。

  1. 首先是您需要獲取訪問令牌。

  2. 第二個問題是顯然調度庫的符號方法使得rdio不快。它刪除尾部斜線,這使得簽名不匹配。

第一個問題很容易解決 - 您只需使用Exchange類,它將爲您完成大部分工作。

第二個問題非常棘手,我剛剛複製了原始的sign方法並更改了部分,即刪除了尾部斜線。

代碼如下。

val ck = new ConsumerKey("YOUR_CONSUMER_KEY", "YOUR_CONSUMER_TOKEN") 

// declare exchange to obtain an access token 
val exchange = new Exchange with SomeHttp with SomeCallback with SomeConsumer with SomeEndpoints { 

    override def http: HttpExecutor = Http 

    override def callback: String = "oob" 

    override def consumer: ConsumerKey = ck 

    override def accessToken: String = "http://api.rdio.com/oauth/access_token" 

    override def authorize: String = "http://api.rdio.com/oauth/authorize" 

    override def requestToken: String = "http://api.rdio.com/oauth/request_token" 
} 

/// we change the default method of the dispatch 
def sign(request: Req, consumer: ConsumerKey, token: RequestToken): Req = { 
    val calc = new OAuthSignatureCalculator(consumer, token) 
    request underlying { r => 
    val req = r.build 
    //!!! here we make change so the trailing slash is not removed 
    val baseurl = req.getURI.toString.takeWhile(_ != '?').mkString("") 
    calc.calculateAndAddSignature(baseurl, req, r) 
    r 
    } 
} 

val response = exchange.fetchRequestToken.right.flatMap { rt => 

    // point your browser to this URL with the given oauth token, we'll get PIN back 
    println(s"Go to https://www.rdio.com/oauth/authorize/?oauth_callback=oob&oauth_token=${rt.getKey}") 
    print("Enter PIN:") 
    val pin = readLine() 

    exchange.fetchAccessToken(rt, pin) 
}.right.flatMap { at => 
    // now we can call API using the consumer key and the access token 
    val request = sign(url("http://api.rdio.com/1/").POST << Map("method" -> "currentUser"), ck, at) 
    val response = Http(request > as.String) 
    response.map(Right(_)) 
} 

response.map { responseOrError => 
    responseOrError.fold(err => println(s"Error $err"), suc => println(s"Response: $suc")) 
    Http.shutdown() 
} 
+0

我沒有使用用戶特定的數據,只從軌道打開元數據。我想我不需要得到令牌。我通過使用Rdio Simple Java Version(https://github.com/rdio/rdio-simple/tree/master/java)發現了一個解決方案,從調度中放棄。 –