URI

目的

Web上に置かれた情報(資源、リソース)に、プログラムから簡単にアクセスできるようにするには?

→資源各々に、プログラムで処理しやすい「名前」をつけよう

URI (Uniform Resource Identifier)

  • インターネット上のリソースの「名前」(識別子, identifier)

    • インターネット上のリソースのURIは、すべてインターネット上で一意に定まる。

    • URL (Uniform Resource Locator) と URN (Uniform Resouce Name) の総称

      • URN : ドメイン名とは独立にリソースにIDを振る方法

        • 例: urn:isbn:9784774142043

        • 現代のWebではほとんど使われない(URI = URL と思ってほぼ差し支えない)

    • 現在のインターネットでは、URL(Uniform Resource Locator)とほぼ同義であると考えて良い。

    • URIはWebで主に使われているが、Webに限った考え方ではない。Web以外の通信でも使うことができるし、パソコンやスマートフォンでアプリケーション内部から別のアプリケーションを起動する際にも用いられることがある。

    • http://www.ietf.org/rfc/rfc2396.txt

    • http://pubinfo.oka-pu.ac.jp/searchApp/viewSyllabus.php?id=1642

    • ftp://ftp.is.co.za/rfc/rfc1808.txt

    • mailto:John.Doe@example.com

    • tel:+1-816-555-1212

URIの利用例

  • ブラウザで表示するページの指定

  • HTML中のリンクの指定(例: <a href=”http://www.example.com/”>example.com</a>

  • スマートフォンのアプリ内でURI tel:+1-816-555-1212 にアクセスすると、電話アプリで +1-816-555-1212 に電話をかける。

URIの意義

http://example.com/about/index.htmlというURIを例にして、URIの意義を述べる。

後述するように、このURIは主に以下の3つの部分からなっている。

  • URIスキーム: http

  • オーソリティ: example.com

  • パス: /about/index.html

この例におけるオーソリティは example.com というFQDNである。1章で述べた通り、FQDNはDNSによってただ一つのIPアドレスに対応づけられる。そして、IPアドレスは(TCP/IP通信の制約として)インターネット上で一意に定まる。また、URIスキーム+パスで、当該コンピュータ(この例ではexample.com)上でリソースが一意に定まる。この2点を合わせることにより、URIはインターネット上におけるリソースの一意性を保証しているわけである。

またURIは、リソースにアクセスする手段をコンピュータに容易に解析可能な方法で記述するという側面を持っている。例えばクライアントが上の例で示されたリソースを取得する場合は、オーソリティで示されたサーバに、URIスキームで示されたプロトコルで接続し、パスで示されたリソースを取得すれば良い。つまり、リソースへのアクセスを完全に自動化することができる。ブラウザでリンクをクリックするだけでリンク先のページに遷移することができるのは、まさにこのURIの性質によるものである。

URIの構文

URIはいくつかの構成要素からなっている。詳細な構文はRFC3986に厳密に定められている。

  • URIスキーム:URIが利用するプロトコルなど。

    • mailtotelなど、以下の構文に従わず、別途構文が定められているURIスキームもある。

  • オーソリティ(authority):各資源の名前の一意性を保証する単位。

    • ホスト名:その資源を提供するコンピュータ名。FQDNまたはIPアドレスである場合が多い。

    • ユーザ情報:URIの指し示すリソースにアクセスするのにユーザ認証が必要となる場合、正当なユーザ名とパスワードをURIに含めることができる。

    • ポート番号:URIにアクセスするためのTCPポート番号。

      • URIスキームで指定されたプロトコルのデフォルトポート番号の場合は省略可(例: HTTPなら80番の場合は省略可)

  • パス:オーソリティ内での資源の識別子。最も簡単な場合、資源(ファイル)への絶対パスになる。

  • クエリパラメータ:検索サービスに対する検索キーワードの指定など、クライアントからサーバに何らかのパラメータを渡したい場合に用いられる。

  • URIフラグメント:リソース内部の、さらに細かい部分の指定に用いられる。

http://www.ietf.org/rfc/rfc2396.txt

  • URIスキーム:http

  • オーソリティ:www.ietf.org

  • パス:/rfc/rfc2396.txt

foo://bar:baz@example.com:8042/over/there?name=ferret&encoding=utf8#nose

  • URIスキーム:foo

  • オーソリティ: bar:baz@example.com:8042

    • ユーザ情報:bar:baz (ユーザID: bar, パスワード: baz

    • ホスト名: example.com

    • ポート番号: 8042

  • パス: /over/there

  • クエリパラメータ: name=ferret&encoding=utf8

  • URIフラグメント: nose

URI構文に関する補足

  • URIスキームとそれ以下の部分は :// で区切られる。

  • ユーザ情報中のユーザIDとパスワードは : で区切られる。

  • ユーザ情報とホスト名は @ で区切られる。

  • ホスト名とポート番号は : で区切られる。

  • ユーザ情報、ポート番号は省略可。

  • パスとクエリパラメータは ? で区切られる。

  • クエリパラメータについて

    • 一つのパラメータは「パラメータ名=値」という形式

    • 複数のパラメータを並べる場合は & で区切る。

  • URIフラグメントとその前の部分は # で区切られる。

URIと文字

URIには、ASCII文字集合の一部の文字(アルファベット、数字、一部の記号)しか使えない。空白記号や日本語の文字などをURIに含めたい場合は、%エンコーディングという方式を用いて、URIに適した文字列に変換(符号化、encode)しなければならない。%エンコーディングの詳細はRFC3986に書かれているが、簡単に言うと「バイトごとに 0x○○ → %○○ と変換」という処理を行う。例を以下に示す。

  • 空白記号(0x40)→ %40

  • 「あ」という文字(UTF-8 では 0xE3 0x81 0x82 の3バイトで表現される)→ %E3%81%82

%エンコーディングの結果から容易に符号化前の文字列を逆変換(復号、decode)できることは明らかであろう。このように、通信路の制限から、通信したいデータを送信側で符号化し、受信側で復号するという事例は、Webに限らずあちこちで見ることができる。

なお、%エンコーディングを使わずに、直接URIの中でUnicode文字集合の文字を使えるように拡張した規格(Internationalized Resource Identifier, IRI)もあるが、まだ普及には至っていない。

よりよいURI

Webでは、リソースを一意に指し示す識別子としてURIが使われ、外部からのリンクを含め、すべてのリソースへのアクセスはURIを使って行われる。ということは、ある情報をWebでリソースとして公開した後、そのリソースのURIを変更してしまうと、そのリソースはWeb上では「行方不明」になってしまうことになる。 つまり、究極的には、リソースに対するURIは未来永劫にわたって不変であることが望ましい。Web開発者は、リソースを公開する前に、そのURIの寿命が可能な限り長くなるようにURIを慎重に設計し、またURIの維持管理をすべきなのである。

参考ページ: Cool URIs don’t change (日本語訳: クールなURIは変わらない)

どういうときにURIが変わってしまうのか

ありがちな例をいくつか挙げてみよう。

  • サーバ機のリプレースでWebサーバのホスト名が変わってしまった

    • http://server1.example.jp/http://server2.example.jp/

  • Webサーバ上で、公開しているファイルの名前を変更した

    • http://example.jp/foo.htmlhttp://example.jp/bar.html

  • Javaで作られていたWebアプリケーションをRubyで再実装した

    • http://example.jp/servlet/LoginServlethttp://example.jp/login.rb

よりよいURIを設計するには

  • 実装依存の情報、時間が経てば変化する可能性のある情報を含めないようにする

    • http://example.jp/ (example.jpという組織がある限り不変)

      • サーバ管理技術で server1, server2 といったサーバ名はURIから隠蔽できる

    • http://example.jp/foo.html (ファイル名を変更してもURIを変えないようにできる)

    • http://example.jp/login (Webアプリケーションの実装言語によらず、ログイン機能があるかぎり不変)

    • http://example.jp/2014/10/16 (2014年10月16日に公開された情報。情報の公開日は時間がたっても不変)

    • http://example.jp/news/latest (最新のニュース)

    • http://twitter.com/kunishi/status/13211 (ユーザkunishiの、ID番号13211のツイート。kunishiがTwitterに登録していて、ツイートを消したりしない限り不変)

  • できる限り、URIはリソースをシンプルに表現するように考える

どうしてもURIを変更しなければならないときは

極力、HTTP リダイレクト(古いURIを新しいURIに転送するHTTPの仕組。後述)を使う。

Last updated