URLとHTTP

HTTPを考える際、どうしても必要になってくるのが、私たちが普段使っているURL(Uniform Resource Locator)という書式です。 ここでは、URLの基本的な構造と、HTTPにおける役割について解説します。

URLという文字列を認識する

URLは一般的に、以下の形式で見るものです。

http://www.example.com/foo/bar.html

この1行で、様々な情報を含めたものとなっています。 ブラウザはこの文字列(URL)を認識して、適切なリクエストを生成します。

URLの書式を分解すると、以下のように読み替えられます。

スキーマ://ホスト名/パス

それぞれの部分をみていきましょう。

スキーマ

スキーマ(scheme)は、このURLにおいて『どんな方法(゠プロトコル)で接続を試みるか』というものを示します。

普段使うhttpであれば、http://と書かれますし。 セキュアな接続を試みる場合はhttps://と書かれます。

注釈

2025年現在においては、 常時TLS/SSL という考え方が広く普及している状況です。 これは、通信の大部分において『常時暗号化された』状態を維持するという考え方です。 そのため、 http://よりはhttps://のほうが一般的になっていると考えていいでしょう。

現在ブラウザにおいてはほぼhttp(s)ですが、他にもいろいろとあります。

  • ftp:// → ftp(ファイル転送プロトコル)によるもの。現在は諸事情によりほぼ使われなくなっており、主要なブラウザ側も対応を終了しています。

  • file:// → ローカルファイルを参照するためのもの。ブラウザによっては対応していないものもあります。

  • mailto: → メールアドレスを指定するためのもの。これを指定すると、メールクライアントが起動します。HTMLのリンクとして使うことで、ブラウザからメールアプリケーションに制御を切り替えることがあります。

また、特に表に出ることはありませんが、OSの内部的な用途で使われることがあります。これは、特定のアプリケーションが独自のスキーマをOSに定義づける行為となっています。 この仕組みを用いることで、特定のアプリケーションを呼び出すようなことがあります。

一例としてZoom(ビデオチャットツール)を出してみましょう。 Zoomでは、WebサイトからローカルにインストールしているZoomのアプリケーションを呼び出すようなことがあります。実際授業でも、Zoomのリンクをクリックすると、最終的にアプリケーションが起動しています。 正確にはミドルウェア部分にですが、OSの構造として、URLスキームとアプリケーションの結びつけを登録する機能を大半が有しています。 URLをこの部分に渡すことで、該当アプリケーションを呼び出す構造になっています。

アプリケーションのインストール時に、OSに対してURLスキーマとの紐付けを依頼しておきます。

sequenceDiagram participant App as アプリケーション participant OS as OS(ミドルウェア部分) App->>OS: URLスキーマ登録を依頼 OS->>OS: スキーマ登録機能を実行 OS->>OS: URLスキーマとアプリケーションを関連付け OS-->>App: 登録完了を通知

そしてブラウザはHTML等に書かれたURLのクリックの際に、内蔵のスキーマ判別機能とOS(ミドルウェア)のスキーマ判別機能で検討します。 その結果として次の動きを決めるようになっています。

flowchart TD A[ユーザーがURLをクリック] --> B{"URLスキームを判別(ブラウザ内→OS)"} B -- http/https --> C[ブラウザでWebページを開く] B -- mailto --> D[メールクライアントを起動] B -- zoom --> E[Zoomアプリケーションを起動] B -- file --> F[ローカルファイルを開く] E -.-> G[OSがアプリケーションハンドラを参照] D -.-> G F -.-> G G --> H[対応アプリケーションに制御を渡す]

上記のように、OSはURLスキームごとにアプリケーションハンドラを登録しており、該当するアプリケーションを呼び出します。

ホスト名とポート番号

ホスト名はその名の通り接続先となるサーバーで、スキーマで指定されたプロトコル手順に従った接続を行う先ということです。

  • 例えばhttpであれば、80/tcpを使って接続を行います。

  • httpsであれば、443/tcpを使って接続を行います。

ホスト名はDNSを用いてIPアドレスに変換してからTCP/IPの手順に基づいて接続を行います。

ただし、ポート番号はスキーム(プロトコル)による標準値を使いますが、なんらかの理由で非標準のポート番号を使いたいということもあります。 例えば開発中のWebアプリケーションの場合、本来の80/tcpを使うことがリスクとなる(下手をすると外部からアクセスされてしまう)こともあります。対策として別のポートを使うこともあるわけです。

この場合、ポート番号はホスト名の後に:を付けて記述できます。 よく見る例としてはこのケースでしょう。

http://localhost:8080/

この場合、8080/tcpを使って、HTTPの手順に沿った接続をするという指示になります。

注釈

この『代替ポート番号』に関しては、利用するフレームワークによるクセみたいなものがあります。 たとえばDjango(PythonでのWebフレームワーク)であれば、デフォルトで8000/tcpを使います。 Node.jsのExpressを用いた場合だと、3000/tcpを使うことが多いです。 また、Ruby on Railsも、3000/tcpを使うことが多いです。

この手のアプリケーションでの代替ポート番号は、開発サーバーを起動する際にオプションで変更可能なものがほとんどです。

注釈

もともとこのポート番号は、HTTPの代替ポートとして/etc/servicesに記載されています。ただし同時にいわゆるプロキシ(キャッシュ機能)としても利用されているものです。

$ cat /etc/services  | grep 8080
http-alt        8080/tcp        webcache        # WWW caching service

パス

パス(path)はLinuxやmacOS、そしてWindowsで使われるファイルシステムのパスと同じ考え方です。 ただし区切り文字(パスセパレーター)は/固定となっています。

この値はサーバーに指定のプロトコルで接続した後に『そのサーバーに対する要求』として使われます。 ただし、パス部分が存在しないことも許容されています。 その場合は、暗黙でスラッシュ(/)が指定されたものとして扱われます。 例えばhttp://www.example.com であれば、http://www.example.com/と同じ意味になります。

URLの解釈ダイアグラム

以上をまとめたとき、以下のようなダイアグラムで表現できます。

sequenceDiagram participant User as ユーザー participant Browser as ブラウザ participant OS as OS(ミドルウェア部分) participant Remote as 接続先ホスト participant Server as サーバー User->>Browser: URLを入力(クリック) Browser-->>Browser: URLを解析 Browser->>OS: (必要なら)URLスキームを判別 OS->>Browser: スキームに応じた処理を返す Browser-->>Remote: 接続を試みる(IP) Remote-->>Server: 接続を試みる(TCP) Server-->>Browser: 接続確認 Browser-->>Server: リクエスト(パス)送信 Server-->>Browser: レスポンス送信(HTMLなど) Browser->>User: 結果を表示(レンダリング)

※ 切断部分は省略します

実際には、ブラウザが追加のリクエストを同じ接続先にそのまま行うこともあります。 また、切断を当面行わずに接続状態を維持することもあります。