ウェブの進化に伴い、URLの扱いにいろいろと変化が生じているので、まとめます。ざっくりとしたまとめなので、厳密ではない記述もある点にご注意ください。
URLとは何なのか?
ただのタグです。過去にはサーバー側のディレクトリ構造を表している、あるいはサーバー側のリソースと対応している、という理解でもよかったのですが、現在ではリソースに対するただのタグでしかありません。
誰がURLを処理するのか
URLが何を表しているのかは、誰がURLを処理するのかによって変わります。URLを処理しているものは、大きく分けて次の三つです。
- ブラウザ
- ウェブサーバー
- アプリケーションサーバー
なお、以下でサーバー、ウェブサーバー、アプリケーションサーバーという三つのサーバーが出てきますが、単に「サーバー」といった時には、その上でウェブサーバーやアプリケーションサーバーが走っているサーバーOSを指しています。
ブラウザにおけるURL
ブラウザにおけるURLは、利用者に「現在の位置」を分かりやすく伝えるための標識です。
たとえば、URLがhttps://qiita.com/
であれば、「トップページにいるんだな」とわかりますし、https://qiita.com/xyz
であれば、「xyzさんのプロフィールページにいるんだな」ということが分かります。実際にはセキュリティ等の絡みでもう少し複雑ですが、基本的にはそれだけです。
これがどういうことかというと、ユーザーにとってURLは単にブラウザに「見せられている」だけのもので、そこから何らかの意味(例えばサーバー側のディレクトリ構造等)を読み取ることはできない、ということです。
試しに、https://qiita.com/
でchromeのデベロッパーツールを開き、コンソールにhistory.pushState(null, null, "xyz")
と打ち込んでみてください。ページが遷移しないまま、URLがhttps://qiita.com/xyz
に変わったと思います。1つまり、ユーザーが「見せられている」URLは、JavaScriptによって容易に書き換え可能であり、そのURLにどんな意味があるのかは、そのサイトの開発者によって自由に定めることができる、ということです。
ウェブサーバーにおけるURL
ウェブサーバーにおけるURLは、HTTPリクエストをサーバーのディレクトリ構造とマッピングさせるためのものです。一般的に、URLと聞いて想像されるものは、ウェブサーバーにおけるURLなのではないかと思います。
ウェブサーバーの主な役目は、HTTPリクエストを受け取り、HTTPリクエスト内のURLに対応したファイルを取得し、HTTPレスポンスに入れて返すことです。2
HTTPリクエストとは、以下のような単なるテキストで、ブラウザ等からサーバーへ送信されます。
GET /about.html HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE5.01; Windows NT)
Host: example.com
このようなリクエストであれば、http://example.com/about.html
へアクセスした、ということです。
中心的な処理となるのが、HTTPリクエスト内のURLとサーバーのディレクトリ構造をマッピングさせる部分です。例えば、http://example.com
というURLをファイルシステムの/www
にマッピングさせる、という設定をしておけば、http://example.com/about.html
というURLに対しては/www/about.html
が返されます。3
アプリケーションサーバーにおけるURL
アプリケーションサーバーにおけるURLは、ブラウザと同じく、標識あるいはただのタグに過ぎません。
アプリケーションサーバーも(HTTPに限れば)HTTPリクエストを受け取りHTTPレスポンスを返すという点ではウェブサーバーと同じです。ただし、アプリケーションサーバーは、HTTPリクエストをプログラムで処理して返す、ということを前提にしています。そのため、アプリケーションサーバーにおけるURLはサーバーのディレクトリ構造とは無関係です。
例として、node.jsでアプリケーションサーバーを作成してみます。以下のコードをsample.js
として保存してください。
const http = require("http");
const server = http.createServer();
server.on("request", (req, res) => {
let msg;
switch (req.url) { // リクエストのURLに応じて分岐
case "/":
msg = "top";
break;
case "/foo":
msg = "foo";
break;
case "/foo/bar":
msg = "bar";
break;
default:
msg = "baz";
break;
}
res.write(msg); // レスポンスにmsgを書き込む
res.end();
});
server.listen(3000, () => {
console.log(
"サーバーを起動しました。 http://localhost:3000 にアクセスしてください。"
);
});
シェルで以下のコマンドを実行すると、アプリケーションサーバーが起動します。
node sample.js
ブラウザでアクセスしてみると、以下のように表示されます。
-
http://localhost:3000
→top -
http://localhost:3000/foo
→foo -
http://localhost:3000/foo/bar
→bar -
http://localhost:3000/baz
→baz -
http://localhost:3000/foobarbaz
→baz
ここから分かるように、アプリケーションサーバーにおけるURLは、開発者にとって都合のいいように定められた、ただのタグに過ぎません。