3
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

GETメソッドでリクエストボディを指定してはいけない(Swift)

Last updated at Posted at 2018-07-22

はじめに

この記事 で「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メソッドなどを使います。

3
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?