銀色うつ時間

思い出すたび何か胸につっかえてるだけ

HTTPってなんなの 1/2

※全2回です

HTTPってなんのことだか分かりますか!

ぼくは分かりません!

でもインターネットだいすきです!

このような人は多いと思う(自分含めて)

さっそく学んでいく。

HTTPとはHyperText Transfer Protocol(ハイパーテキスト・トランスファー・プロトコル)の略称である。WebブラウザとWebサーバの間でHTMLなどのコンテンツの送受信に用いられる通信プロトコルのことで、ITIFによりRFC2616で規定されている。ハイパーテキスト転送プロトコルとも呼ばれる。乱暴な言い方をすれば、僕らがブラウザを通じてやってることはだいたいHTTPという規格の上で通信している、ということ。通信プロトコルについてまでまとめると大変なことになるので、また時間のあるときに。とはいえwikipediaに載っている程度の情報はさらっと目を通しておいた方がよい。

通信プロトコル - Wikipedia

http://ja.wikipedia.org/wiki/%E9%80%9A%E4%BF%A1%E3%83%97%E3%83%AD%E3%83%88%E3%82%B3%E3%83%AB

もうちょい概要

ティム・バーナーズ・リーらが1990年に世界初のWebサーバーとWebブラウザを開発した。サーバーとブラウザ間による通信を行うために彼らが設計した通信プロトコルこそが、HTTPであり、トランスポートプロトコルとしてTCPを使用している。HTTPは名前の通りHTMLやXMLの転送を主な目的としているが、周知の通り音声や映像などのバイナリ形式も転送可能である。リクエスト-レスポンス型のプロトコルであり、クライアント(ブラウザ側)がサーバにリクエストメッセージを送信する。サーバはこれにレスポンスメッセージを返し、基本的にこの時点で初期状態に戻る。つまりこれは、サーバ側がクライアントの状態を保存しないことを意味する(これを解決するCookieについては後述)。他には、ポート番号80をデフォルトで使用すること、TLSによって暗号化されることでセキュリティを保った通信はHTTPSと呼ばれることなどが挙げられる。

HTTPリクエスト

先に述べたように、リクエストを投げるのは常にクライアント側である。逆を返せば、サーバーはリクエストがなければ応答しない。HTTP通信を開始できるのはクライアント側のみなのだ。基本的な考え方は非常に単純で、リクエストは「何を」「どうして」欲しいのかをサーバーに伝える。URLが「何を」、メソッドが「どうして」に当たる。

HTTPリクエストの構成

基礎を確認するのだから静的なウェブサイトが好ましい。試しにhttp://www.2ch.netにアクセスしたときに自分のブラウザから投げたリクエストを確認してみた。firebug(chromeの場合は付属の開発者ツール)なんかですぐに調べられる。

GET / HTTP/1.1
Host: www.2ch.net
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:14.0) Gecko/20100101 Firefox/14.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ja,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
Referer: http://www.google.co.jp/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0CE4QFjAA&url=http%3A%2F%2Fwww.2ch.net%2F&ei=pZYzUPf9POrwmAWUoYHACw&usg=AFQjCNFc01jYm6KymcLkeIbDliJNSoyYog&sig2=hRwJ1GN7Jx_gudPqtBVQMw
If-Modified-Since: Mon, 09 Jul 2012 16:28:11 GMT
If-None-Match: "159100-10b9-4c468198a9cc0"-gzip
Cache-Control: max-age=0

HTTPリクエストには

  • HTTPリクエスト行
  • HTTPヘッダ
  • データ本体(メッセージボディ)

の3つのパートが存在する。HTTPリクエストの1行目が、リクエスト内容を示すHTTPリクエスト行(リクエストライン)で、ここには「メソッド」「URI」「HTTPのバージョン」の3つの情報が含まれている。記述方法は以下。URIに関しては後述。

[メソッド][空白][URI][空白][HTTP バージョン]
今回のリクエストではこの部分(ドメインは省略されている、というかサーバー側の絶対パスなのでスラッシュのみ。もちろん階層を下がればindex.htmlなどといった文字列が出現する)
GET / HTTP/1.1

今回のようにGETメソッドの場合、HTTPリクエストではデータ本体は送られない。メソッドがPOSTの場合は、HTTPヘッダの後にデータ本体が続く。HTTPヘッダに関してだが、GETメソッドを用いているこのリクエストでは2行目以降はすべてHTTPヘッダである。POSTなど他のメソッドだった場合は次行からメッセージボディが続くことになる。

GET, POSTを初めとするHTTPメソッド

GETやPOSTといったメソッドは私達に馴染み深いが、実は他にもHTTPメソッドは存在する。おさらいも兼ねて以下にまとめる。

  • GET
    • 指定されたURIのリソースをサーバーから取り出すHTTPの最も基本的な動作。
  • POST
    • GETとは反対にクライアントがサーバにデータを送信する。Webフォームや掲示板の投稿などをイメージすると分かりやすい。GETの場合と同じく、サーバはクライアントにデータを返すことができるが、クライアント側から見ればGETは受け取るメソッドであり、POSTは送信するメソッドなので混同しないようにする。

あとはあまり馴染みのないメソッドたちだが、いつか出会うこともあるだろう。

  • PUT
    • 指定したURIにリソースを保存する。URIが指し示すリソースが存在しない場合は、サーバはそのURIにリソースを作成する。画像のアップロードなどが代表的。
  • DELETE
    • 指定したURIのリソースを削除する。
  • OPTION
    • サーバを調査する。例えば、サーバがサポートしているHTTPバージョンなどを知ることができる。
  • HEAD
    • GETと似ているが、サーバはHTTPヘッダのみ返す。クライアントはWebページを取得せずともそのWebページが存在するかどうかを知ることができる。例えばWebページのリンク先が生きているか、データを全て取得することなく検証することができる。
  • TRACE
    • サーバまでのネットワーク経路をチェックする。サーバは受け取ったメッセージのそれ自体をレスポンスのデータにコピーして応答する。WindowsのTracertやUNIXのTracerouteとよく似た動作。
  • CONNECT
    • 暗号化したメッセージをプロキシで転送する際に用いる。
URIとは

先に触れたURIについて。URLと名前も概念もなんだか混同してしまいそうだが、一応別の識別子である。が、ことHTTPにおいては殆ど同義といえる。めんどいから概要はWikipediaから。

Uniform Resource Identifier(ユニフォーム リソース アイデンティファイア、URI)または統一資源識別子(とういつしげんしきべつし)は、一定の書式によってリソース(資源)を指し示す識別子。1998年8月にRFC2396として規定され、2005年1月にRFC3986として改定された。URI はUniform Resource Locator (URL) の考え方を拡張したものである。

URIはhttp/httpsftpなどのスキームで始まり、コロン(:)による区切りのあとにスキームごとに定義された書式によってリソースを示す。また、URIによって示されるリソースはコンピュータが扱うデータに限らず、人や会社、書籍などを示すことも可能である。

(アイデンティファイアとか名前かっこいいな・・・)

要は膨大なウェブの中で、「hogehoge区にお住まいのfoobarさんちのfugafugaさん」みたいに一意の存在を識別するための仕組みであると考えられる。もう少し詳しく見ていこう。

http://www.2ch.net:80/foo?bar#bazというURIについて考える。この文字列は

  • http
  • www.2ch.net
  • 80
  • foo
  • bar
  • baz

に分けられるが、それぞれどんな解釈がされるのだろうか。以下に見ていく。

  • scheme
    • 最初の文字列はデータリソースにアクセスするための手法を識別する。ここでのスキームは当然http。
  • host
    • 次のwww.2ch.netはホスト名、つまりそのリソースを持っているコンピュータ(たいていはサーバー)の名前を指定する。IPアドレスによる指定も可能だが奨励されていない。
  • port
    • ファイル共有ソフトなんかのお陰で開発に携わらない人間にも馴染みが深いポート番号。これを指定する。先に述べたようにデフォルトのHTTPが扱うポート番号はWell known portとして80番が予約されてるが、それ以外の番号を使用することも可能。8000や8080などをテスト用として利用することや、セキュリティの観点から別の番号を用いることもある。ポート番号が明示されていない時は80を使用する。ポートに限らずTCP/IP関連はまた別の機会に。
  • abs-pass
    • absolute pass、すなわち絶対パス。そのコンピューター内でのリソースの場所を指定する。スラッシュ(/) をディレクトリ区分に用いる。
  • query
    • クエリ文字列、よくクエリパラメータとか呼ぶ。絶対パスとの区切りには?を利用する。指定したリソースに情報を流す場合に用いるのだが、GETメソッドを利用する場合にも使われる。
  • fragment
    • 部分識別子。絶対パスとの区切りには、#を用いる。fragmentもURIの中に含まれるが、"http_URL"の中にはfragmentは含まれない。HTTPにおいて、fragmentはリソース内の特定部分を指すものであり、即ちfragmentはリソース取得後にのみ意味を持つ。

がどう使われるか。どの部分がクライアントで解釈されるか、どの部分がサーバーで解釈されるか。

HTTPヘッダ

2ch.netにアクセスしたときのリクエストにも、hostやrefererなどといった文字列があった。これらがHTTPヘッダである。クライアントとサーバーは、HTTPヘッダを使ってデータやソフトウェアの情報をやりとりしている。HTTP/0.9では、データの取得のみを目的としていたので、HTTPヘッダというものは存在しなかったが、wwwが活用され始めるにつれリソースサイズや更新時刻といった「取得するリソースに関連する情報」や、ユーザエージェントの種類やそれを参照するリソースのURIなどの「クライアント側の情報」をやりとりする必要性に迫られ、実際のリソースとは別のメタ情報を扱うものとして、HTTPヘッダが開発されたという経緯がある。ヘッダの書式は、

フィールド名: 内容

という形式で記述される。代表的なリクエストヘッダを列挙する。

  • Accept
    • サーバのレスポンスに含まれるメッセージボディで受け入れることが出来るコンテンツタイプと各コンテンツタイプの相対的な優先度を指定するリクエストヘッダ。
  • Accept-Charset
    • レスポンスで返されるメッセージボディの文字コードを指定するリクエストヘッダ。Acceptと同じく複数指定でき品質係数も設定できる。定義済み文字セットはIANAが管理している。
  • Accept-Encoding
  • Accept-Language
    • レスポンスの言語(人間の言語)に対する優先度を指定する。言語コードはISO-639の2文字の省略コードを用いる。書き方は他のAccept-群と変わらず。
  • Host
    • Hostヘッダはhttp/1.1における唯一の必須ヘッダである。必須の理由として、ネームベースのバーチャルホストが用いられた際の名前解決に必要となることが挙げられる。バーチャルホストでは、たとえば192.168.0.100というIPアドレスを持つ1台のホストサーバがあったとして、これにhost1.2ch.net,host2.2ch.net, host3.2ch.netという3つのドメインを割り当てたとする。これによって、クライアントから見るとまるで3台のホストサーバがあるように見えるので、IPアドレスを“節約”することができるのだ。この時にhttp://host3.2ch.net/hogeへリクエストをするとどうなるだろうか。クライアントがリソースを取得するためには、まずホスト名をIPアドレスに変換する、すなわち名前解決をしてサーバを探し出した後にリクエストをする必要がある。(参考:DNSの仕組みについて http://d.hatena.ne.jp/arerreee/20120814/1344960272)だがこの場合リクエスト先のIPアドレスには3つのホストが同居しているので、このままでは望むリソースを取得することができない。対策として、それぞれにIPアドレスを付与する方法もあるがIPv4の資源を無駄にすることになる。そこで、Hostヘッダを使用し予めホスト名をメタデータに明示しておくことで名前解決を行なっている、というわけだ。
Host: www.2ch.net
  • User-Agent
    • ブラウザの種類やOSの情報。アクセスしているのがブラウザではなく検索エンジンのクローラの場合、Googlebotなどの名前が入る。歴史的経緯からどのブラウザもMozillaを入れていたりする。また、モバイル端末やキャリア、OSの識別もUser-Agentを利用して行う。
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:14.0) Gecko/20100101 Firefox/14.0.1
  • Referer
    • どのページから発生したリクエストなのかを示す。つまり、ページAに記されたリンクをクリックしてページBに行った場合に、ページBへのHTTPリクエストにリファラとしてページAが入ってくる。同様に、ページCを表示する際にページ内で使われている画像をリクエストする際に、画像のHTTPリクエストにリファラーとしてページCが入る。リファラの活用はクロスサイトリクエストフォージェリ(いわゆるCSRF)対策としても一般的であろ、統計的用途にもよく使われる。余談だが、本来の参照元という意味の英単語は"referrer"であるにもかかわらず、HTTPリファラの場合は意図的に"referer"と綴る。これは、HTTPが策定された時にヘッダ名を間違ったスペルで書いてしまい、それが今でも使われているという歴史的経緯のためである。仕様上のヘッダ名は"referer"であるため、特にHTTPヘッダを直接扱うようなソフトウェアプログラムの場合、"referrer"と綴ると意図通りに動作しない場合すらある。ここではgoogleから辿ってきたので次のような内容となる。
Referer: http://www.google.co.jp/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0CE4QFjAA&url=http%3A%2F%2Fwww.2ch.net%2F&ei=pZYzUPf9POrwmAWUoYHACw&usg=AFQjCNFc01jYm6KymcLkeIbDliJNSoyYog&sig2=hRwJ1GN7Jx_gudPqtBVQMw
  • Cookie
    • クッキー(Cookie)は実のところRFCによって定義されていいない非標準HTTPヘッダである。元々ユーザエージェント(Webブラウザ)によって保存される「小さな」ファイルを指す。主に「状態管理」のために利用され、ログイン情報やショッピングカートを実現するために利用されている。Cookie、Set-Cookieという専用のHTTPヘッダ。
  • Content-Disposition
    • これも非標準。Content-Dispositionは、本来MIME仕様に従うデータの提示的情(presentational information)を転送するためのヘッダだが、HTTPはメッセージの形式がMIMEに似ているので、HTMLフォームからmultipart dataをアップロードする際にも流用されている。つまりファイルのアップロードに用いられるヘッダ。filename属性を使うと、転送されたデータのファイル名をデータの送信側が示すことができる。

次回に向けて

HTTPについてまとめるとプロトコルやポートなどといったTCP/IPの領域、さらにはリクエストラインのメソッドやリクエストヘッダなどのおびただしい形式などが出現して頭が破裂するかと思った。特にリクエストヘッダにはヘッダごとに更に属性を保持していたりでやっかい。少しずつ覚えて記事にしていこうと思う。やっぱ本1冊程度は読んでおくべきだよなーこの辺、などと。

次回は残りのHTTPレスポンスについて書く。

何か間違いがあったらご指摘ください。