GETとPOSTの違いについて

# はじめに
GETとPOSTの違いを最低限理解することはWebサービスの開発を始めようとする初学者にとって最初の障壁の一つであると考えています。

これはあなたが実現したい機能があった時に、GETでもPOSTでもどちらでも同じことができてしまうことによるものだと思います。

本記事は、初学者を対象にGETとPOSTの違いを大まかに噛み砕いて説明する記事になります。
そしてあなたが機能を実装したい時に、ある程度適切にGETかPOSTを選べるようになることが達成したいことになります。

# Webサービスにおける通信の基本
GETとPOSTの話に入る前に、少しクライアントとサーバがどうやってやりとりをしているのかについて話します。

Webにおいてサーバとクライアント間のやりとりは基本的にHTTPというプロトコルを用います。

- クライアントからサーバへの要求することをリクエストといいます。
- サーバからブラウザへ応答することをレスポンスといいます。

Webの世界でのやりとりは基本的にリクエスト/レスポンスで成立しています。

例えば、検索をする場合では、
- クライアントはサーバに検索に該当するサイトを教えてくださいと要求します(リクエスト)
- サーバは要求に対して、必要な処理をして、その結果を返答します(レスポンス)
この結果、クライアントはレスポンスを元に検索結果を表示します。

※ HTTPにもHTTP/1.1やHTTP/2やHTTP/3が存在したり、他にもキャッシュなど学んだ方が良いことはたくさんありますが、一度に多くのことを学ぶことは大変です。
まだプログラミングが手に馴染んでいなければきっと慣れることの方が大切な時期です。
今は簡単のためにざっくりと、上記の例のような粒度で、通信がどうやって行われているかイメージできれば良いはずです。

# GET/POSTとは
クライアントとサーバがやり取りする際、HTTPで通信するという話をしましたが、HTTPにはいくつかの仕様が取り決められています。

GET/POSTというのはその仕様で取り決められた、HTTPメソッドの一部です。
今回は説明しませんが、この仕様には他にもHEAD/OPTIONS/PUT/DELETEなどが定義されています。

あなたが実装したい機能は表面上はGETでもPOSTでも動くかもしれませんが、セキュリティなどいくつかの観点から、この取り決められた仕様則って実装することが推奨されます。

つまり実装する機能が実現したいことに対して、GETとPOSTでより適している方を選ぶ必要があります。

## GET
GETは指定したリソースの表現を転送するようにリクエストするメソッドです。
つまり、何か情報を検索したり取得するために使うためのメソッドになります。

例えば、ブラウザでURLを入力し検索するとき、あなたは無意識にGETメソッドを使っています。

また仕様で安全かつ冪等であると定義されているため、基本的に読み取り専用な機能に対して使うべきメソッドになります。

GETを使うとどのような処理をしていたとしてもクライアントには安全なAPIだと見なされます。
これは、クライアントからはサーバがどのような処理をやっているかを知ることはできないためです。

## POST
POSTは指定したリソースを実装した機能に従って処理をする機能になります。

主に登録処理や更新処理などの、書き込みがありリソースが更新される可能性のある処理に対して使うメソッドになります。

例えば、以下のような例があります。

- HTMLの `<form></form>`に入力された内容をDBへ登録する
- ブログの記事を投稿する
- 新しいユーザを登録する
- 既存のデータに新しい情報を付加する

また、GETとは反対に冪等でないかつ安全でないと定義されています。

# もう少し表面的な違いについて考える
## リクエストパラメータの付加の方法
クライアントからサーバへリクエストするときに、商品IDなどリクエストに何か情報を渡したいことがあると思います。

GETはURLにクエリとして追加することが可能です。

```
GET: /foo/bar?itemId=xxxx-xxxx
```

これはGETの `URL`による表現はすべて回収すべきという仕様のためです。

一方、POSTはBodyをリクエストに含めることも可能です。また一般的にあまり使われませんが、クエリを追加することもできます。

```
POST: /foo/bar?user="taro"
param:{"itemId": "xxxx-xxxx"}
```

GETはURLに直接付加するので目でパラメータを見ることができます。POSTはBodyに含めることが可能で目に見えない形での送信が可能です。

恐らく、これが最も分かりやすい違いだと思います。

### 余談
POSTは目に見えないから安全だという話が稀にあがりますが、半分は間違っています。
URL上から見えないだけで通信を盗聴すれば見ることができます。安全性を担保するには通信を暗号化をしなければいけません。

(目に見えてしまう以外の理由もありますが、)セキュリティ観点から、機密性の高いデータの送信にGETを使うべきではないというのが正しい解釈になります。

## ブックマーク
以下のコメントを@Zuishin さんからいただきました。追記いたします、ご指摘ありがとうございます。

>何がちがうかの最たるものである「ブックマークできるかどうか」について触れておいた方が良いのではないでしょうか？

ブラウザのブックマークに登録した場合、URLを開く際にGETで開かれます。

例えば、フォームに名前を入力して検索結果を`/foo/bar` で表示させる機能について考えます。

`name: "taro"` で検索したとします。

- 検索処理がPOSTの場合、ボディに含めてリクエストするので `/foo/bar` というURLで結果を取得することになります。
- 検索処理がGETの場合, URLで表現されるため `/foo/bar?name=taro` というURLで検索結果が表示されます。

つまり、GETだと `/foo/bar?name=taro`というURLをブックマークできるので、`name=taro`で検索したときの検索結果をブックマークできます。

POSTの場合はボディに含めるため、検索結果をブックマークできません。

※JavaScriptを用いればPOSTでもブックマークできるかもしれません。

## 性質
HTTPメソッドごとに持っている性質が違います。

ここでは詳しく説明しませんが、
- GETは冪等かつ安全かつキャッシュ可能です。
- POSTは冪等でないかつ安全でないです。また特定の条件下でキャッシュ可能です。

## 使用用途
持つべき性質が違うと話しましたが、性質が違うのであれば、使用用途も変わってきます。

- GETはリソースを取得するときに使うものです。
- POSTはリソースに対して特有の処理をするときに使うものです。

### 余談
RESTでは以下のような振舞いを推奨しています。

- GETは情報を取得するときに使うものです。
- POSTは新しい情報の登録をするときに使うものです。

# 終わりに
Webには色々な思想や技術があります。この記事に関係するもので言えば、もしかしたらRESTやGraphQL,もしくはSOAPという文字を見たことがある方もいるかもしれません。

またこの記事に書いてあることは、Webの世界のほんの一部のその表面にあるものでしかありません。
しかしながら初学者のほとんどが必ず通る道で、きっとその時は小難しい呪文のような印象を受ける方が多いと思います。

この記事によって、初学者の方が少しでも次のステップへ進めたら幸いです。

# 参考
- https://developer.mozilla.org/ja/docs/Web/HTTP/Methods
- https://tools.ietf.org/html/rfc7231#section-4
- https://triple-underscore.github.io/RFC7231-ja.html