はじめに
この記事 で「http://」のAPIを実行できるようにしたのですが、まだ以下のエラーが発生して落ちます。
エラーを転記します。
zipcloud.ibsnet.co.jp
The data couldn’t be read because it isn’t in the correct format.
domain: "NSCocoaErrorDomain" - code: 3840
"NSDebugDescription" : "Invalid value around character 0."
postcode-jp.appspot.com
HTTP load failed (error code: 303 [4:-2201])
finished with error - code: 303
このエラーでいくらググっても解決できなかったので苦戦しました。
やっと解決できたのでその方法を紹介します。
環境
- OS:macOS High Sierra 10.13.1
- Xcode:9.2
- Swift:4.0.3
原因
タイトルで原因を言っていますが、 URLRequest.httpBody
に値を入れているためでした。
基本的にGETメソッドではリクエストボディを指定してはいけなく、APIによってはエラーが発生します。
空を指定してもエラーが発生しました。
// bad
var request = URLRequest(url: url)
let requestBody = [:]
request.httpBody = try! JSONSerialization.data(withJSONObject: requestBody, options: [])
解決策
URLRequest.httpBody
に値を入れずにGETメソッドを実行するとエラーが発生しなくなります。
リクエスト作成メソッドを汎用的にする場合、引数が nil
でないときのみリクエストボディに値を代入するようにするといいです。
HTTPClient.swift
static private func createRequest(requestBody: [String: Any]?, url: URL, method: HTTPMethod, contentType: ContentType) -> URLRequest {
var request = URLRequest(url: url)
request.httpMethod = method.rawValue
request.setValue(contentType.rawValue, forHTTPHeaderField:HeaderField.contentType.rawValue)
// リクエストボディをディクショナリからJSONへシリアライズする
if let _requestBody = requestBody {
do {
request.httpBody = try JSONSerialization.data(withJSONObject: _requestBody, options: [])
} catch let error {
print(error.localizedDescription)
fatalError()
}
}
return request
}
GETメソッドでリクエストを作成するときは常にリクエストボディを nil
で渡します。
HTTPClient.swift
static public func get(urlString: String, queriesDictionary: [String: String]?) -> Any {
let url = createUrl(urlString: urlString, queriesDictionary: queriesDictionary)
return runHTTPMethod(requestBody: nil, url: url, method: .get, contentType: .json)
}
結論
GETメソッドは用法・用量を守って正しく使い、リクエストボディを指定しないようにしましょう。
リクエストボディを送信したい場合、PUTメソッドなどを使います。