3
0

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.

【Swift】GETリクエストでパラメータを送信する方法

Last updated at Posted at 2023-04-09

記事の背景

API を利用する際に、GET リクストで値を送信しようとしたところエラーが発生しました。
そこで、この記事では、GET リクエストで値を送信するとなぜエラーが起こるのか、そして GET リクエストで正しく値を送信する方法について説明します。

開発環境

  • Swift
  • Xcode 14.2

エラーコード

GET method must not have a body

本論

GETで値を渡すとエラーになる理由

エラーコードにも書いてある通り、基本的に GET メソッドではリクエストボディを指定してはいけません。

理由は主に 2 つあります。

  • GET リクエストの目的に違反する
  • HTTP/1.1 の仕様

GETリクエストの目的

GETリクストは、リソースを取得するために存在します。
リクエストボディは、リソースを取得するためのものです。
リクエストボディを使用すると、それが変更や作成を意味する POST や PUT リクエストと混同される危険性があります。

HTTP/1.1の仕様

HTTP/1.1の仕様の4.3節において、GET リクエストはリクエストボディを持つべきではないとされています。
もし、GET リクエストボディを持たせると、サーバーやプロキシなどの中継機器がリクエストボディを無視する可能性があります。
そのため、期待した結果を得られない場合があります。

以上の理由から、GET リクエストでリクエストボディを指定することは避けるべきです。

GETリクエストで正しく値を送信する方法

上記の理由で GET リクエストでは、リクエストボディの指定ができないため、適切にデータを送信するにはクエリパラメータを活用しましょう。これにより、簡単かつ正確に値を伝えることができます。

クエリパラメータとは、WEB ブラウザや他のアプリケーションが WEB サーバにデータを送信する際、送信先の URL の末尾に特定の形式で表記される情報です。

しかし、アプリケーションによっては GET リクエストだけでなく、POST や PUT などの他のリクストも使われることがあります。

そこで、Swift の構造体を活用し、GET リクエストとそれ以外のリクエストに分けて処理を行う方法が効果的です。

実際に、コードを見てみると、以下のようになります1

Swift
enum HttpMethod: String {
    case get = "GET"
    case post = "POST"
    case put = "PUT"
    case delete = "DELETE"
    case patch = "PATCH"

    func urlRequest(url: URL, data: Data?) throws -> URLRequest? {
        var request = URLRequest(url: url)
        switch self {
        case .get:
            guard let data = data else {
                request.httpMethod = rawValue
                return request
            }

            guard var components = URLComponents(url: url, resolvingAgainstBaseURL: true),
                let dictionary = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else { return nil }

            components.queryItems = dictionary.map { URLQueryItem(name: $0.key, value: "\($0.value)") }
            guard let getUrl = components.url else { return nil }
            var request = URLRequest(url: getUrl)
            request.httpMethod = rawValue
            return request

        case .post, .put, .delete, .patch:
            request.httpMethod = rawValue
            request.httpBody = data
            return request
        }
    }
}

まとめ

API を活用する際、GET リクエストで値を送信しようとしてエラーが発生します。
これは GET リクエストの目的と HTTP/1.1 の仕様および推奨事項に反しているためです。
そのため、GET リクエストでリクエストボディを使用するのは避けるべきです。
代わりに、値を送信する際にクエリパラメータを利用するのが効果的です。

  1. このコードはある方のQiita記事を参考にさせていただきました。

3
0
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
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?