目次
- 目次
- はじめに
- HTTPとは
- HTTPのバージョンの違い
- HTTPリクエストの構造
- HTTPの8つメソッド
- HTTPレスポンスのステータスコード
- RESTとは
- REST APIの特徴
- REST APIの成熟レベル
- REST APIで注意すべきこと
- より詳しくHTTPを学びたい人は
- 参考資料
- MyEnigma Supporters
はじめに
最近、趣味でWebアプリを作っているのですが、
サーバとクライアント間の処理を書く時に、
HTTPの知識の無さを感じていました。
GETやPOSTというメソッドを使って、
なんとなくクライアントからデータを送信したり、
サーバ側のデータを取得出来ていましたが、
それらの違いや、その他のメソッド、
そしてエラーのステータスコードなど、
分からないことが多かったです。
ググればなんとなくわかりますが、
すべてを体系的に理解しているというには
程遠かったので冒頭の書籍と下記のリンクの資料を
使って勉強してみました。
今回は、自分のようなWeb初心者のために
HTTPやRESTの基礎的な内容とわかりにくい所、
そしてWebサービスを作る時に、
どのように使用されるのかを簡単に説明したいと思います。
HTTPとは
HTTPはHypertext Transfer Protocolの略で、
ブラウザとWebサーバ間でデータを通信する用のプロトコルです。
Hypertext Transfer Protocol - Wikipedia
元々はhtmlを送信する用のプロトコルだったので、
このような名前ですが、実際は静止画や音声、動画、PDFなど
様々なデータの転送に使われてます。
OSI参照モデルでは、アプリケーション層に位置するプロトコルで、
その下のTCP/IPを使って通信をします(デフォルトのポート番号は80番)。
HTTPは下記のような特徴を持ったプロトコルです。
サーバ・クライアントによるリクエスト・レスポンス通信
ステートレス性(クライアントの状態を保持しない)
まず一つ目は、HTTPは
クライアント(ブラウザ)が、
データのリスエストを送信し、
それを受け取ったWebサーバ(サーバ)が、
レスポンスとしてデータを返すという形の通信をします。
二つ目は、ステートレス性です。
これはサーバー側はクライアントの状態を管理しないという方法で、
サーバはそれぞれのクライアントとの過去のやりとりを
保存しないということになります。
これによりクライアントからの一つ一つのリクエストには
必要なすべての情報が含まれるようになるため、
大量のクライアントをサーバが管理しやすくなります。
またサーバを複数台に増やした時も、
どのサーバにリクエストを送っても問題なくなるため、
スケーラビリティが良くなります。
一方、同じクライアントが同じサーバに通信する時は、
毎回同じようなデータをリクエストとして送信してしまうので、
通信の無駄が多くなってしまうという問題があります。
HTTPのバージョンの違い
最初のHTTPのメジャーバージョンである
HTTP1.0では、一つのリクエストとレスポンスに対して、
毎回TCPのコネクションを貼り直していましたが、
これは多数のデータをやりとりする場合には、
通信の無駄が発生していました。
その後策定されたHTTP1.1では、
一つのコネクションで複数のリクエストとレスポンスが可能になっています。
(キープアライブ機能)
現在はこのHTTP1.1が最も広く使われているHTTPのバージョンです。
最近、HTTP/2という次世代のHTTPプロトコルが作られました。
また普及はしていませんが、
リソースの取得の最適化が進むため、
今後、広く使われていくと思われます。
「HTTP/2」がついに登場! 開発者が知っておきたい通信の仕組み・新機能・導入方法 (1/3):CodeZine(コードジン)
HTTPリクエストの構造
ブラウザなどのクライアントがサーバに送信する
HTTPリクエストのデータ構造に関しては、
下記の記事がわかりやすいと思います。
[Web] HTTPリクエストの中身を学んでみた。GETやPOSTの違いなど - YoheiM .NET
ちなみに、HTTPリクエストはテキストデータで、
HTTPリクエスト
HTTPヘッダ
HTTPボディ
の3つの部分に分けることができます。
ちなみに下記の記事のように、
PC or Mac版のChromeの場合、開発ツールを使うことで
簡単にHTMLリクエストヘッダなどを見ることができます。
Chrome で WEB レスポンスヘッダ と リクエストヘッダの内容を確認する | MacBook Air とWordPressでこうなった
HTTPの8つメソッド
HTTPは実は8つしかメソッドを持っていません。
しかもその内、よく使われるのは下記の1-5番で、
簡単なWebアプリの場合、
下記のGETとPOSTだけしか使わないことが多いようです。
それぞれのメソッドについて簡単に下記で説明していきます。
1. GET
すでに存在しているURIのデータを取得するメソッドです。
おそらく最も使用頻度の高いメソッドで、
HTML、画像、動画のデータなど、
様々なデータを取得する時に使用されるメソッドです。
またデータを取得する際に、
クライアント側から、サーバ側にパラメータを送信することができます。
それは、GETメソッドでURIを指定した時に、
URIの後ろに付ける文字列です。
これをクエリストリングといいます。
一般的には、URIのはてなマーク(?)以降であり、
アンドマーク(&)でパラメータを区切ります。
下記はクエリストリングの例です
これにより、GETで大量のデータを取得できるが、
一部のデータしか不要な場合に、idで必要なデータを指定したり、
limitで、データの最大数を指定できます。
このクエリストリングはクライアントとサーバ間でデータをやりとりするのに
非常に便利ですが、URIにデータを含めるため、
データが見えやすく、また改ざんしやすいという問題があります。
加えて、このURIのデータは、サーバだけでなく、プロキシなどにもログが残ってしまいます。
また、あまり大量のデータをURIに含めることができない場合もあります。
(IEの場合URIの制限があり2048文字が最大)
そこで、ユーザのデータなどの重要なデータを、
クライアントから、サーバーに送信したい場合は、
次のPOSTメソッドを使います。
また、バイナリデータをする場合には、
Rangeヘッダーと組み合わせることで、
複数のHTTPの要求でデータを取得することができます。
また、Acceptヘッダーを使うことで、
リソースを取得するフォーマットを指定することもできます。
2. POST
URIに新しいリソースを追加するメソッドです。
リソースが追加された場合は、
HTTP 状態コード 201 (Created)を返します。
先ほどのGETがクライアントにとって、
メインのデータ受信方法である一方、
POSTはクライアントからサーバ宛への
メインのデータ送信方法になります。
先ほどのGETとは異なり、
クライアント側からのデータが、
HTTPリクエストのボディ部に格納されるため、
大量のデータを送信したりすることが可能です。
また、重要性の高いデータを暗号化してボディ部に格納して
送信したりすることができます。
(URIにデータを入れるGETと異なり、データはプロキシなどには保存されません。)
加えて、細かいGETとPOSTの挙動の違いですが、
ブラウザで戻るボタンを押す時、
POSTメソッドが呼ばれていた場合は、警告が出ますが、
GETメソッドの場合は出ません。
また、リソースを新規登録するという意味では、
後述のPUTと混同しやすいですが、
POSTはユーザがリソースのURIを指定せずに、サーバが新しいURIを指定して返す一方、
PUTはユーザ側がリソースのURIを指定するという区別もできます。
3. HEAD
URIのヘッダデータのみを取得するメソッドです。
GETメソッドと同じように、データを取得するメソッドですが、
GETメソッドはデータのボディ部のデータも一緒に取得してしまうので、
データの更新日時のみを取得したい場合は、通信の無駄が発生してしまいます。
そこでこのHEADメソッドを使うと、データのヘッダ部のみを取得できるため、
データの更新日時や、データのサイズのみを取得したい場合に、
効率的にデータを取得できます。
大きなバイナリのデータをやり取りしたい場合は、
このHEADでサイズを確認して、
GETとRangeヘッダーで、部分的にデータを取得していく方法もよく利用されます。
4. PUT
すでに存在しているURIの内容を作成・置換するメソッドです。
PUT 要求は、POSTやDELETEと異なり、べき等である必要があります。
クライアントが同じ PUT 要求を複数回送信した場合、
結果は常に同じにならないといけません(同じリソースが同じ値で変更されます)。
このPUTを使うことにより、
URIで指定したリソースが無い場合は作成し、
ある場合は、更新することが可能になります。
上記のPOSTもデータを作成するメソッドですが、
POSTとの使い分けはどうすれば良いでしょうか?
基本的には、同じデータをPUTで送っても、
同じ結果になる場合にPUTを使います。
加えて、
冒頭の参考資料や、下記の記事にある通り、
HTTPメソッドのPOSTとPUTの使い分け - アインシュタインの電話番号
PUTではURIをクライアントが指定するため、
サーバとクライアントが密結合になりやすくなるため、
基本はURIをサーバが決定できるPOSTを使用するようにした方がいいようです。
5. DELETE
URIの内容を削除するメソッドです。
各URIに登録されているリソース(ある日のブログの記事など)
を削除する時は、このDELETEメソッドを使って、
指定されたURIのリソースを削除することができます。
6. OPTIONS
URIに対して利用できるメソッドの一覧を取得するメソッドです。
すべてのリソースは上記のメソッドに対応していないことがあります。
例えば、あるリソースはDELETEできない設定になっている場合などです。
そのような場合、対応していないメソッドを呼ばれた時に
エラーコードを返しても良いのですが、
事前にクライアントにあるリソースの対応している
メソッドを知らせるメソッドがあります。
それが、OPTIONSメソッドです。
このメソッドでURIを指定すると、
サーバ側が対応している場合、
指定されたURIのリソースが対応するメソッドを返してくれます。
7. CONNECT
プロキシにトンネリング通信を要求するメソッドです。
SSLなどで暗号化したデータを送信する場合、
プロキシは中身のデータを判断できないため、
このCONNECTメソッドにより、
中身のデータのパケットをサーバまで
ただ右から左に転送するようにしてもらえます。
こちらのメソッドも個人用Webアプリでは殆ど使用されないメソッドです。
また、このCONNECTメソッドは悪用されることが多いようです。
8. TRACE
クライアントからのリクエストをそのまま返すメソッドです。
基本はサーバまでの経路をチェックする用のメソッドで、
ちゃんとサーバまで繋がっていれば、リクエストと同じ内容が
サーバから返信されます。
こちらのメソッドも殆ど使用されていないメソッドです。
また、このTRACEメソッドも悪用する方法もあるみたいです。
9. PATCH
PATCH メソッドはURL先のリソースの一部を変更するメソッドです。
リソースがJSONで表される場合は、
JSONの一部のフィールドの値を更新したり、
新しいフィールドを追加したり、
値にnullを指定することで、フィールドを削除することができます。
HTTPレスポンスのステータスコード
上記のメソッドでクライアントがサーバにリクエストを出すと、
サーバは処理結果をレスポンスのステータスコードとして返します。
詳細は下記を参照して頂きたいですが、
三桁目の番号で、おおよそ下記のように分類されています。
100番台: 処理中
200番台: 肯定的な応答
300番台: 転送要求(Web APIの場合は使わない)
400番台: クライアント側のエラー
500番台: サーバ側のエラー
レスポンスとステータスコード
それぞれのメソッドで、データに対する処理が成功したときに、
ステータスコードとデータを返すかどうかは、
下記が一般的だそうです。
- PUT 200と共にデータを返す
- PATCH 200と共にデータを返す
- POST 201と共にデータを返す
- DELETE 204でデータを返さない
ステータスコード401と402の違い
401 はあなたが誰だかわからない
402 はあなたは誰だかわかるけど、処理が許可されてない
と意味します。
RESTとは
RESTは、Web サービスを設計するためのアーキテクチャ代表的な方法で
Representational State Transfer (REST) の略です。
RESTそのものは、HTTPに依存したものではありませんが、
RESTに基づいたAPIである、REST APIは、
HTTPベースであることが多いです。
REST APIの特徴
REST APIの特徴としては下記が上げられます。
リソースを中心に設計される。ここでのリソースはデータやサービスなど、APIが提供するあらゆるものを指す。
全てのリソースは一意の識別子としてURIを持ち、それらは複数形の名詞で表される。
多くのAPIのリソースは、クライアントとのやり取りに、JSON表現を使う。
REST APIのそれぞれの要求は基本的にステートレスであり、atomicです。
APIのバージョニングは、URLに入れ込む、クエリパラメータに入れる、Custom Headerに入れるなどが代表的な方法です。
REST APIの成熟レベル
下記の様なレベルが設定されており、
殆どのREST APIは最低でもLevel 2までサポートしています。
Level 0: 1 つの URI が定義され、すべての操作がこの URI に対する POST 要求
Level 1: リソースごとに個別の URI を作成
Level 2: HTTP メソッドを使用して、リソースに対する操作が定義される
Level 3: ハイパーメディアを使用します (後述の HATEOAS)。
REST APIで注意すべきこと
サーバの負荷を増やさないために、小さいデータを話す小さいAPI(chattyなAPI)を沢山準備しない。
クライアントにファイルフォーマットを設定して欲しいときは、クエリパラメータを使う良い
URLやAPIの名前に動詞を使わない
レスポンスのJSONやXMLは、できるだけフラットにする。(深い階層を作らない)
レスポンスのJSONやXMLに、ヘッダーに入れるべき情報(共通の最初のレイヤーデータ:エンベロープ)を入れない。
レスポンスのJSONの名前はキャメルケースを使う
配列をそのまま返すより、オブジェクトで配列を包むと、セキュリティが向上する
レスポンスではコンテンツタイプをちゃんと設定すべき、UnitTestでテストもすべき。
一つのリクエストの計算時間が長い場合は、複数のHTTP要求でデータを取得できるように非同期化を検討する。
より詳しくHTTPを学びたい人は
下記の書籍がおすすめです。
HTTPの基礎から応用まで学ぶことができます。
参考資料
yohei-y:weblog: REST 入門(その5) 四つの動詞 -- GET, POST, PUT, DELETE
MyEnigma Supporters
もしこの記事が参考になり、
ブログをサポートしたいと思われた方は、
こちらからよろしくお願いします。