MyEnigma

とある自律移動システムエンジニアのブログです。#Robotics #Programing #C++ #Python #MATLAB #Vim #Mathematics #Book #Movie #Traveling #Mac #iPhone

Web初心者のためのHTTP、REST入門

 

目次

はじめに

最近、趣味でWebアプリを作っているのですが、

サーバとクライアント間の処理を書く時に、

HTTPの知識の無さを感じていました。

 

GETやPOSTというメソッドを使って、

なんとなくクライアントからデータを送信したり、

サーバ側のデータを取得出来ていましたが、

それらの違いや、その他のメソッド、

そしてエラーのステータスコードなど、

分からないことが多かったです。

 

ググればなんとなくわかりますが、

すべてを体系的に理解しているというには

程遠かったので冒頭の書籍と下記のリンクの資料を

使って勉強してみました。

docs.microsoft.com

 

今回は、自分のようなWeb初心者のために

HTTPやRESTの基礎的な内容とわかりにくい所、

そしてWebサービスを作る時に、

どのように使用されるのかを簡単に説明したいと思います。

 

HTTPとは

HTTPはHypertext Transfer Protocolの略で、

ブラウザとWebサーバ間でデータを通信する用のプロトコルです。

Hypertext Transfer Protocol - Wikipedia

 

元々はhtmlを送信する用のプロトコルだったので、

このような名前ですが、実際は静止画や音声、動画、PDFなど

様々なデータの転送に使われてます。

 

OSI参照モデルでは、アプリケーション層に位置するプロトコルで、

その下のTCP/IPを使って通信をします(デフォルトのポート番号は80番)。

OSI参照モデル - Wikipedia

 

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リクエストはテキストデータで、

  1. HTTPリクエスト

  2. HTTPヘッダ

  3. 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のはてなマーク(?)以降であり、

アンドマーク(&)でパラメータを区切ります。

 

下記はクエリストリングの例です

http://www.google.co.jp/search?q=Yahoo&lr=lang_ja&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:ja:official&client=firefox-a

 

これにより、GETで大量のデータを取得できるが、

一部のデータしか不要な場合に、idで必要なデータを指定したり、

limitで、データの最大数を指定できます。

 

このクエリストリングはクライアントとサーバ間でデータをやりとりするのに

非常に便利ですが、URIにデータを含めるため、

データが見えやすく、また改ざんしやすいという問題があります。

1-4. クエリストリングから情報が漏れる

加えて、この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メソッドの場合は出ません。

Tech Tips: GETとPOSTの違い

 

また、リソースを新規登録するという意味では、

後述の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レスポンスのステータスコード

上記のメソッドでクライアントがサーバにリクエストを出すと、

サーバは処理結果をレスポンスのステータスコードとして返します。

 

詳細は下記を参照して頂きたいですが、

HTTPステータスコード - Wikipedia

三桁目の番号で、おおよそ下記のように分類されています。

  • 100番台: 処理中

  • 200番台: 肯定的な応答

  • 300番台: 転送要求(Web APIの場合は使わない)

  • 400番台: クライアント側のエラー

  • 500番台: サーバ側のエラー

 

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を沢山準備しない。

  • レスポンスのJSONやXMLは、できるだけフラットにする。(深い階層を作らない)

  • レスポンスのJSONやXMLに、ヘッダーに入れるべき情報(エンベロープ)を入れない。

  • 一つのリクエストの計算時間が長い場合は、複数のHTTP要求でデータを取得できるように非同期化を検討する。

docs.microsoft.com

 

より詳しくHTTPを学びたい人は

下記の書籍がおすすめです。

HTTPの基礎から応用まで学ぶことができます。

 

参考資料

yohei-y:weblog: REST 入門(その5) 四つの動詞 -- GET, POST, PUT, DELETE

myenigma.hatenablog.com

myenigma.hatenablog.com

myenigma.hatenablog.com

myenigma.hatenablog.com

myenigma.hatenablog.com

myenigma.hatenablog.com

  

MyEnigma Supporters

もしこの記事が参考になり、

ブログをサポートしたいと思われた方は、

こちらからよろしくお願いします。

myenigma.hatenablog.com