記事の背景
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。
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 リクエストでリクエストボディを使用するのは避けるべきです。
代わりに、値を送信する際にクエリパラメータを利用するのが効果的です。
-
このコードはある方のQiita記事を参考にさせていただきました。 ↩