`curl –header $1` と同じことを Swift で実現したい (NSURLSessionのヘッダの記述)

投稿者: Anonymous

以下の curl のコマンドを Swift で実現したいです。しかしヘッダ部分の記述方法がわかりません。

curl -X GET 
     --header "X-Auth-Token: abcdef" 
     https://devapi.thecurrencycloud.com/v2/rates/detailed?buy_currency=EUR&sell_currency=USD&fixed_side=buy&amount=1000

こちらが私のコードです。しかしエラーとなってしまいました。解決方法をご教示頂きたいです。

func exchangerate(){
    let token = "abcdef"
    let request = NSMutableURLRequest(URL: NSURL(string: "https://devapi.thecurrencycloud.com/v2/rates/detailed")!)
    var buyCurrency = "EUR"
    var sellCurrency = "USD"
    var fixSide = "buy"
    var amount = "1000"
    var postString:NSString = "buy_currency=(buyCurrency)&sell_currency=(sellCurrency)&fixed_side=(fixSide)&amount=(amount)"

    request.HTTPMethod = "GET"
    request.setValue(token, forHTTPHeaderField: "X-Auth-Token")
    request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)

    let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
        data, response, error in

        if error != nil {
            println("error=(error)")
            return
        }

        println("response = (response)")

        let responseStringExchangeRate = NSString(data: data, encoding: NSUTF8StringEncoding)
        println("responseStringExchangeRate = (responseStringExchangeRate)")
    }
    task.resume()

}

エラー:

error=Error Domain=NSURLErrorDomain 
      Code=-1005 
      "The operation couldn’t be completed. (NSURLErrorDomain error -1005.)" 
      UserInfo=0x7fea7b4d63f0
      {
         NSErrorFailingURLStringKey=https://devapi.thecurrencycloud.com/v2/rates/detailed,
        NSErrorFailingURLKey=https://devapi.thecurrencycloud.com/v2/rates/detailed,             _kCFStreamErrorDomainKey=4,
        _kCFStreamErrorCodeKey=-4, 
        NSUnderlyingError=0x7fea7d805ba0
        "The operation couldn’t be completed. (kCFErrorDomainCFNetwork error -1005.)"
      }

解決

request.HTTPMethod = "POST" ですかね?

以下を test.swift として保存。(以下、修正します)

import Foundation

func exchangerate(){
    let token = "abcdef"
    // let request = NSMutableURLRequest(URL: NSURL(string: "https://devapi.thecurrencycloud.com/v2/rates/detailed")!)
    var buyCurrency = "EUR"
    var sellCurrency = "USD"
    var fixSide = "buy"
    var amount = "1000"
    //var postString:NSString = "buy_currency=(buyCurrency)&sell_currency=(sellCurrency)&fixed_side=(fixSide)&amount=(amount)"
    let request = NSMutableURLRequest(URL: NSURL(string: "https://devapi.thecurrencycloud.com/v2/rates/detailed?buy_currency=(buyCurrency)&sell_currency=(sellCurrency)&fixed_side=(fixSide)&amount=(amount)")!)


    request.HTTPMethod = "GET"
    //request.HTTPMethod = "POST"

    request.setValue(token, forHTTPHeaderField: "X-Auth-Token")
    // request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)

    let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
        data, response, error in

        if error != nil {
            println("error=(error)")
            return
        }

        println("response = (response)")

        let responseStringExchangeRate = NSString(data: data, encoding: NSUTF8StringEncoding)
        println("responseStringExchangeRate = (responseStringExchangeRate)")
    }
    task.resume()
}

// for debug.
exchangerate()
sleep(10)

実行。

$ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift test.swift
response = <NSHTTPURLResponse: 0x7f8390793810> { URL: https://devapi.thecurrencycloud.com/v2/rates/detailed } { status code: 401, headers {
    Connection = "keep-alive";
    "Content-Length" = 176;
    "Content-Type" = "application/json";
    Date = "Wed, 07 Jan 2015 00:11:17 GMT";
    Server = nginx;
    "X-Content-Type-Options" = nosniff;
    "X-Request-Id" = 2693396219771410479;
} }
responseStringExchangeRate = Optional({"error_code":"auth_failed","error_messages":{"username":[{"code":"invalid_supplied_credentials","message":"Authentication failed with the supplied credentials","params":{}}]}})
$

追記

(以下、ちょっと乱暴な説明です、ごめんなさい)

質問にあった GET でのリクエストは、サーバに対して、

GET /v2/rates/detailed HTTP/1.1
Host: devapi.thecurrencycloud.com
X-Auth-Token: abcdef
(空行)
buy_currency=EUR&sell_currency=USD&fixed_side=buy&amount=1000

のような文字列を送信しているのだと思います。

対して私が回答したものは、

GET /v2/rates/detailed?buy_currency=EUR&sell_currency=USD&fixed_side=buy&amount=1000 HTTP/1.1
Host: devapi.thecurrencycloud.com
X-Auth-Token: abcdef
(空行)

という文字列を送信します。

また、POST の場合は、

POST /v2/rates/detailed HTTP/1.1
Host: devapi.thecurrencycloud.com
X-Auth-Token: abcdef
(空行)
buy_currency=EUR&sell_currency=USD&fixed_side=buy&amount=1000

といった文字列を送信します。

(空行)以前が、いわゆるHTTP リクエストヘッダで、以降はリクエストボディ(request.HTTPBody)です。

サーバ側で、GET でリクエストを受けたなら、 リクエストボディは読まないで、レスポンスをしてしまうのだと思います。また、POST であれば、リクエストボディまでちゃんと読んでくれてたのだと思います。

なので、エラーメッセージが

"The operation couldn’t be completed. (NSURLErrorDomain error -1005.)

となって、「まだ、サーバに話したいことがあるのに(リクエストボディを送っていないのに)。。」(超意訳)

となったのだと思います。

回答者: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *