Webサーバー・インフラ
URL
post:
URLは、Webページや画像などのリソース(資源)を、その場所やアクセス方法によって示す文字列です。 ブラウザのアドレスバーに表示されるほか、リンクの行き先やHTTPリクエストの宛先を決めるために使われます。
URLとは?
URLはUniform Resource Locatorの略です。
ブラウザはhttps://utakamo.com/glossary/のようなURLを読み取り、どの方式で、どのサーバーへ接続し、サーバーに何を求めるかを決めます。
URLを構成する部分
次のURLを例に、各部分の役割を見ていきます。
https://www.example.com:8443/docs/guide.html?lang=ja#install
| 部分 | 例 | 役割 |
|---|---|---|
| スキーム | https | リソースを扱う方式を示す。後ろに:が続く |
| ホスト | www.example.com | 接続先をドメイン名またはIPアドレスで示す |
| ポート | 8443 | 接続先の機器で、どのプログラムにつなぐかを番号で示す |
| パス | /docs/guide.html | サーバーに求めるリソースを示す |
| クエリ | lang=ja | ?の後に続き、検索語や表示条件などの追加の情報を渡す |
| フラグメント | install | #の後に続き、取得したリソースの中の位置などを示す |
スキーム
Webページではhttpsとhttpがよく使われます。httpsは、通信を暗号化するHTTPSで接続することを示します。
スキームにはWebの通信方式のほかに、メールの宛先を示すmailto:や、PC内のファイルを示すfile:などもあります。
https://の//は、その後ろにホストなどの接続先が続くことを示す区切りです。
一方、メールの宛先を表すmailto:info@example.comには//がありません。
ホスト
ホストには、www.example.comのようなドメイン名のほか、192.0.2.10のようなIPアドレスも書けます。
IPv6のアドレスは、ポートの区切りの:と区別するためhttp://[2001:db8::1]/のように角括弧で囲みます。
ドメイン名の場合、ブラウザはDNSで接続先のIPアドレスを調べます。 日本語などを含むドメイン名は、DNSに問い合わせる前にASCIIの文字列へ変換されます。 この仕組みはIDN(国際化ドメイン名)とPunycodeの解説で扱っています。
ポート
1台のサーバーでは、Webサーバーやメールサーバーなど複数のプログラムが通信を待ち受けることがあります。ポート番号は、そのうちどれにつなぐかを区別する番号です。
httpsのURLでポートを省略すると443番、httpでは80番が使われます。
ローカルで開発用のサーバーを動かすときは、http://127.0.0.1:8000/のように、既定以外のポートを明示することがよくあります。
パス
パスは/で区切った階層の形をしています。
ファイルの保存場所に似た見た目ですが、パスがそのままサーバー内のファイルの位置を表すとは限りません。この違いは「URLとファイルの場所の違い」で説明します。
スキームとホストは大文字・小文字を区別しない一方、パスは区別されるものとして扱われます。
/Docs/と/docs/が同じ内容を返すかどうかは、サーバーのファイルシステムや設定によって異なります。
クエリ
クエリには、?q=url&page=2のように名前=値を&でつなぐ形がよく使われます。
ただし、これはHTMLのフォームなどで広く使われている書き方で、URLの構文としてはこの形に限られません。
CSSやJavaScriptのURLにバージョン番号のクエリを付け、更新後に古いファイルが使われないようにする方法もあります。 詳しくはブラウザキャッシュの解説で扱っています。
フラグメント
HTMLでは、id="install"を持つ見出しなどがある場合、フラグメントに#installを指定したURLを開くとその位置まで移動します。
フラグメントはブラウザの中で処理され、HTTPリクエストの宛先には含まれません。
そのため、#より後ろの違いは、通常のリクエストではサーバーに伝わりません。ただし、ページのスクリプトがフラグメントを読み取って表示を変えたり、別途サーバーに送ったりすることはあります。
ブラウザが送るリクエストの形はHTTPリクエスト・HTTPレスポンスの解説で確認できます。
ユーザー情報
あまり使われませんが、ホストの前に@で区切ってユーザー名を書くこともできます。
RFC 3986では、ここにユーザー名:パスワードの形でパスワードを含める書き方は非推奨とされています。URLは画面やログに残りやすく、パスワードが漏れるおそれがあるためです。
また、https://utakamo.com@example.net/の接続先はutakamo.comではなく、@より後ろのexample.netです。
URLの先頭に見えるドメイン名だけでは、接続先を判断できません。
紛らわしいドメイン名を使う手口は、タイポスクワッティングやIDNホモグラフ攻撃の解説で扱っています。
パーセントエンコーディング
URLのパスやクエリに日本語や空白などを含めるときは、それらを%と2桁の16進数の組み合わせで表すことがあります。これをパーセントエンコーディングと呼びます。
?や#のように区切りの意味を持つ記号も、URLの部分や用途に応じて、区切りではなく値として扱うためにエンコードします。
例えば「用語」をUTF-8で表し、各バイトを%付きの16進数にすると、次のようになります。
用語 → %E7%94%A8%E8%AA%9E
ブラウザのアドレスバーでは日本語のまま表示されても、URLをコピーして貼り付けるとこの形になることがあります。 なお、HTTPやHTTPSのURLでは、ホストに含まれる日本語はDNSで使えるようにPunycodeを含むASCIIのドメイン名へ変換されます。
絶対URLと相対URL
スキームから始まる完全な形のURLを絶対URLと呼びます。
一方、HTMLのリンクや画像の指定では、../img/figure.pngのように一部だけを書く相対URLもよく使われます。
相対URLは、基準になるURL(ベースURL)と組み合わせて絶対URLに変換されます。ベースURLは通常そのページ自身のURLですが、HTMLのbase要素で指定することもできます。
次の表は、ベースURLがhttps://example.com/docs/guide/index.htmlの場合の解決結果です。
| 相対URL | 解決後のURL | 意味 |
|---|---|---|
install.html | https://example.com/docs/guide/install.html | 同じ階層 |
../img/figure.png | https://example.com/docs/img/figure.png | 1つ上の階層から |
/css/style.css | https://example.com/css/style.css | ホストの最上位から |
?page=2 | https://example.com/docs/guide/index.html?page=2 | クエリだけを変える |
#install | https://example.com/docs/guide/index.html#install | 同じページ内の位置 |
install.htmlのように相対パスから始まるURLは、ベースURLのパスの最後の/より後ろを取り除いた位置から解決されます。
そのため、ベースURLがhttps://example.com/docs/guide/ならinstall.htmlは/docs/guide/install.htmlになりますが、末尾の/がないhttps://example.com/docs/guideでは/docs/install.htmlになります。
../などを使った相対URLは、ページを別の階層へ移動すると指す先が変わります。
ページの移動後に画像やCSSが読み込まれなくなった場合は、相対URLが移動前の階層を前提にしていないかを見直します。
URLとファイルの場所の違い
URLのパスは、サーバーに「どのリソースがほしいか」を伝えるための名前です。サーバーの中でどのファイルを返すかは、サーバー側の設定によって決まります。
例えば、基本的な静的配信では、URLのパスに対応するファイルがドキュメントルートの中から探されます。
/glossary/のようにディレクトリを指すURLでは、その中のindex.htmlなどを返す設定がよく使われます。
さらに、URLの書き換えやWebアプリケーションのルーティングを使う場合は、パスと同じ名前のファイルが存在しないこともあります。
逆に、ファイルがサーバーにあっても、ドキュメントルートの外にあるなど公開する設定になっていなければ、URLからはアクセスできません。 URLの書き方が正しくても、そのURLが指すリソースが存在し、取得できるとは限りません。
URLとドメイン名・オリジンの違い
ドメイン名は、URLのホストに書かれる名前です。https://utakamo.com/glossary/というURLの中で、utakamo.comがドメイン名に当たります。
ドメイン名から接続先のIPアドレスを調べる仕組みは、DNSの解説記事で扱っています。
また、HTTPやHTTPSのURLでは、スキーム・ホスト・ポートの組み合わせをオリジンと呼びます。ブラウザはオリジンを、あるページのスクリプトが別のオリジンのデータを読み取れるかどうかを判断する単位として使います。
同じドメイン名でも、httpとhttpsのようにスキームが違えば別のオリジンになります。
URIとの関係
URLに似た言葉にURIがあります。RFC 3986では、リソースを識別する文字列全般をURI、そのうち場所や取得方法によってリソースを示すものをURLとして区別しています。 一方、ブラウザの仕様をまとめるWHATWGのURL StandardはURLという呼び方に統一しています。この記事でも、Webで使う文字列をURLと呼んでいます。
参考資料
- RFC 3986: Uniform Resource Identifier (URI): Generic Syntax — URIの構文、相対参照の解決、パーセントエンコーディング
- WHATWG: URL Standard — ブラウザでのURLの解析と用語
- RFC 9110: HTTP Semantics —
http・httpsスキームと既定のポート - HTML Standard: Fragment navigations — フラグメントによるページ内の移動