URI、URL、URNの解説


![Logto cover_Unveiling URI, URL, and URN.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3845573/1ce38920-c57e-98a1-9c00-95d6001283ac.png)


この記事は https://blog.logto.io/unveiling-uri-url-and-urn/ からのものです

Webアプリを開発する際、さまざまなWebサービスを呼び出す必要があります。異なるWebサービスの通信と接続を設定する際に、URI、URL、URNの概念に頻繁に遭遇します。通常、これらを区別するのが難しく、混同や誤用が生じがちです。この記事では、それぞれの違いを説明し、技術ブログやドキュメントを読む際、または他のエンジニアとコミュニケーションを取る際にこれらの概念を正しく理解し使用するための例を提供します。

## URLとは？

URL（Uniform Resource Locator）は、インターネット上のリソースのWebアドレスや場所を提供します。通常、Webページ、ファイル、サービスの場所を指定するために使用されます。URLは、Web上のリソースにアクセスするための標準化された形式を提供します。これは、Web閲覧、リンク、インターネット通信の重要な要素です。

URLはいくつかの部分から成り立っており、それぞれがリソースのアドレスとアクセスするためのプロトコルを定義します。以下のURLを例にして、各部分の機能を一つずつ説明します。

```
https://example.logto.io:8080/blogs/index.html?param1=value1&param2=value2#introduction
```
1. **スキーム:** リソースにアクセスするために使用されるプロトコルやスキームを指定します。HTTP（Hypertext Transfer Protocol）、HTTPS（HTTP Secure）、FTP（File Transfer Protocol）などがあります。

   このURLのスキームは `https` です。

2. **ホスト:** ホストは、リソースをホスティングしているサーバーのドメイン名やIPアドレスを指定します。

   このURLのホストは `example.logto.io` です。

3. **ポート:** （オプション）ポートは、リソースにアクセスするためのホスト上の特定のポート番号を表します。ポートが指定されていない場合、標準ポートが使用されます。

   HTTPの標準ポートは80、HTTPSの標準ポートは443です。

   このURLのポートは `8080` です。

4. **パス:** （オプション）パスは、サーバー上のリソースが存在する特定の場所やディレクトリを示します。ディレクトリやファイル名を含むことができます。

   このURLのパスは `/blogs/index.html` です。

5. **クエリパラメータ:** （オプション）クエリパラメータは、リソースに渡される追加のパラメータです。動的なWebアプリケーションでよく使用されます。パスの後に `?` 記号で区切られます。

   このURLのクエリパラメータは `param1=value1&param2=value2` です。通常、キーと値のペアで表され、ペアは `&` 記号で区切られます。実際の使用シナリオでは、スペースなどの文字を避けるためにエンコードが必要です。

6. **フラグメント識別子:** （オプション）アンカーとも呼ばれ、リソース内の特定の位置を示します。

   このURLのアンカーは `#introduction` です。

また、ファイルサービスを利用したり、多くのWebページの「お問い合わせ」ボタンがURLにリンクされています。例えば：

- `ftp://documents.logto.io/files/legal/soc_ii.pdf`
- `mailto:contact@logto.io?subject=Enterprise%20quota%20request`

## URIとは？

URIは "Uniform Resource Identifier" の略です。Webページ、ファイル、サービスなどの特定のリソースを識別する文字列です。URIは、標準化された形式を使用してリソースを一意に識別および位置付ける方法を提供します。

URIは主に2つの要素から構成されます：

1. **スキーム:** リソースにアクセスするために使用されるプロトコルやスキームを示します。
2. **リソース識別子:** アクセスまたは参照される特定のリソースを識別します。リソース識別子の形式は、使用されるスキームによって異なります。

文法的な観点から、URIは主に[RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986)で指定されているように、URLと同じ形式に従います。

このURI形式はURLと似ていますが、Web上のリソースにアクセスできることを保証するものではありません。この形式を使用することで、名前空間の競合を減らすことができます。

前述のセクションでは、リソースを識別するだけでなく、そのリソースの場所も特定するURLを紹介しました。したがって、URLはURIの適切なサブセットです。

## URNとは？

URNはURLやURIほど一般的ではないかもしれません。これは "Uniform Resource Name" の略で、リソースが存在しなくなった場合でもリソースを永続的に識別することを目的としています。

URLとは異なり、URNはリソースの場所に関する情報を提供せず、単に識別するだけで、純粋なURIのようなものです。具体的には、URNは「urn」スキームを持つURIの一種であり、[RFC 2141](https://datatracker.ietf.org/doc/html/rfc2141)で説明されている次の構造を持ちます：

`<URN>:<NID>:<NSS>`

1. **URN:** 通常は `urn` です。
2. **名前空間識別子 (NID):** URNを定義し管理する一意の名前空間や識別子システムを表します。これにより、識別子の文脈が提供され、その一意性が保証されます。名前空間の例としては、ISBN（国際標準図書番号）などがあります。
3. **名前空間固有文字列 (NSS):** 指定された名前空間内でリソースを一意に識別する文字列です。この識別子自体は、リソースの場所やアクセス方法に関する情報を含みません。

例えば、有名なコンピュータシステムを紹介する書籍[CSAPP](https://www.isbns.net/isbn/9780134092669/)には、ISBN番号があり、そのISBN番号をURN `urn:isbn:9780134092669` として表します。

URNは、SAMLプロトコルにおけるアサーションのようなさまざまな標準プロトコルでよく使用されます。これはURN `urn:oasis:names:tc:SAML:2.0:assertion` に対応します。

ソフトウェアエンジニアリングでは、URN命名規則に従って独自のシステム内で特定の目的のためにURNを定義することもできます。例えば、Logtoでは、Organizationを有効にするために、SDKを使用する際に設定に `urn:logto:scope:organizations` スコープを追加する必要があります。各Organizationにも専用のURN `urn:logto:organization:{orgId}` があります。

## 結論

URI、URL、URNの関係は、以下のベン図を使用して説明できます：

![Screenshot 2024-07-26 at 16.18.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3845573/28fd137c-5394-0e57-5f82-59d76be03805.png)


URI、URL、およびURNはすべて異なるリソースを識別するために使用できますが、リソースの位置を正確に特定できるのはURLのみです。

URIとURLは、HTTP、HTTPS、FTPなどのさまざまなスキームをサポートできますが、URNは `urn` スキームのみをサポートしていると考えられます。

すべてのURLやURNはURIですが、すべてのURIがURLやURNであるわけではありません。