共同開発をしているときにHTTPメソッドでGETリクエストによる情報取得の際に、JSONの構造体をサーバーの送ろうと設計されてたことがあり、そのコードが動かなかったのでこれに関する問題を解消していきたいと思います。
まずHTTPメソッドとは
HTTPメソッドは、通信プロトコルであるHTTPにある標準メソッドであり、HTTPリクエストの目的を示すために使用されます。
HTTPメソッドは以下のようになっています。
メソッド名 | 機能 |
---|---|
GET | リソースの取得 |
POST | リソースの作成、追加 |
PUT | リソースの更新 |
PATCH | リソースの一部更新 |
DELETE | リソースの削除 |
HEAD | リソースのヘッダーを表示 |
OPTIONS | リソースの通信オプションを示す。 |
CONNECT | サーバーとの間にコネクションを作る |
TRACE | パスに沿ってループバックテストを行う |
GETリクエストの使い方
一般的と言う言い方をしていいのかわかりませんが、GETリクエストはパスパラメーターに識別子をつけたり、クエリパラメーターで欲しいデータの条件をリクエストする形式が一般的だと思います。
例えば、ローカルのポート8080を使ってサーバーを立ち上げたとします。
そのサーバーに対してhogehoge
という識別子のリソースの取得を行うときはcurl
コマンドで下のように使用します。
curl http://localhost:8080/hogehoge
catというキーワードに合致するリソースが欲しい場合は下のようにクエリパラメータを使ったりすると思います。
curl http://localhost:8080/?keyword=cat
GETメソッドはJSONを含めることができる
JSONなどのデータ構造体をペイロードとしてリクエストするのは、GETメソッド以外で行うというのが一般的ですし、なんならGETメソッドでそれをすることはできないと思っている方も多いと思います。
実は、GETメソッドでもJSONを使ったリクエストをすることは仕様上可能です。
ですが、あまり使用されていない理由はなぜなのでしょう?
どうしてGETメソッドにJSONを含めないのか
仕様的な問題
一つにHTTPの仕様やライブラリなどの仕様が要因の一つとして挙げられます。
みなさんよく調べるときに使うであろう下のサイトでは以下のように書かれていました。
GET を使用したリクエストはデータをリクエストするためだけに使用してください(データを含めるべきではありません)。
メモ: GET リクエストで本文(ペイロード)を送信すると、実装によってはリクエストを拒否することがあります。これは仕様書では禁止されていませんが、その意味は未定義です。 GET リクエストでは本文を送るのを避けた方がいいでしょう。
GETメソッドは単にデータをもらうだけで、サーバーにペイロードを送るように設計されていないというのが大きそうです。
送れないようにされているわけではありませんが、想定している動作がされるとは限らなそうです。
また、調べてでてきただけですが、axiosなどのJavaScirptの通信ライブラリではJSONを含めてGETリクエストすることができない?と書かれてるものも一部見つけました。
今回の共同開発でもaxiosでGETを送っていたため、動かなかった可能性は大きそうです。
読み取り専用にしたい
GETメソッドは、読み取り専用にして安全にしたいという考え方があります。
安全とは、メソッドがサーバーの状態を変更しないということを指します。
読み取り専用にするためにもJSONは送らないという考えがあります。
GETメソッドでJSONでデータを送れてしまうと、サーバーでそのJSONを元に書き換えるという記述ができてしまうからです。
そもそも書き換える記述をするなという話ではありますが、ヒューマンエラーで起こす可能性もゼロではありません
共同開発において、なるべくデータを書き換えることがないように実装することは重要なことなので、JSONボディを含めることなく、URIで指定するようにすることでそのような事態を防ぐことができます。
キャッシュの問題
HTTPリクエストで送った内容はキャッシュをすることができます。
しかし、JSONなどのペイロードが含まれているとキャッシュが機能しないそうです。
なのでリソースの取得はURIで指定します。
GETメソッドでJSONを送るケースはあるのか?
仕様上、クエリパラメーター数が制限される場合はJSONを送ることがあるそうです。
RFC7230では8000文字ほどを推奨しているそうですが、そんな8000文字も書くことなんてあるのでしょうか...
まとめ
一般的には、GETリクエストを使ってJSONを送らない方が良さそうです。
共同開発をする際でも、いくらJSONを送れるとはいえ、パスパラメーターやクエリパラメーターで指定する場合がほとんどだと思うので、スムーズに開発を進めるためにもGETメソッドでJSONを送るように設計しないようにしましょう。