[1] [[URL]] は同じものを表すにも関わらず複数の表現方法がある場合が数多く存在します。
その一方で、 [[URL]] [WEAK[(によって表されるもの)]] が同一かどうか判定したいこともあります。
それ故、2つの [[URL]] が同一かどうかを判定する'''[[比較演算]]'''を定義する必要が生じます。
比較演算の定義に当たっては'''[[正規化]]'''の方法を規定し、それによる[[正規形]]の比較を用いることもあります
[WEAK[(もちろん[[正規化]]なしで[[比較]]を定義することもあります)]]。
なお、[[正規化]]は純粋な[[比較]]のため以外にも[[部品]]の取り出しや[[パターン一致]]のために使われることがありますし、
[[人間]]が読むためにも便利です。

[22] [[URL]] は表現の自由度が極めて高く、しかも様々な場面で使われているため、
[[比較]]と[[正規化]]の方法は色々定義されています。
[[比較]]や[[正規化]]の[[コスト]]を無視できないというのも様々なバリエーションが生まれる要因となっています。

* URL の構文解析、解決、比較と正準化

[15] [[URL Standard]] の登場まで、 [[URL]] (として解釈される文字列) 
に対する[[構文解析][URLの構文解析]]、[[解決][URLの解決]]、
[[比較][URLの比較]]と[[正準化][URLの正準化]]といった各[[演算]]の関係は明確に理解されていませんでした。

[18] [[URL Standard]] は[[構文解析][URLの構文解析]]、[[解決][URLの解決]]、
基本的な[[正準化][URLの正準化]]を1つの不可分の演算として改めて正確に定義し、
[[比較][URLの比較]]はその結果について 
(あるいは場合によっては文脈依存の更なる[[演算]]を経たものについて) 行うものとしました。

;; [19] [[URLの構文解析]]を参照。

* 単純文字列比較

''[[URLの単純文字列比較]]''

[23] 最も単純なのが、 [[URL]] を単純に[[文字列]]として比較する、というものです。

[24] ほとんど自明な比較方法に思えますが、単純比較すら、いくつかバリエーションが考えられます。
- [25] 与えられた [[URL]] を本当に純粋に[[文字列]]として[[比較]]する
- [26] 与えられた [[URL]] が[[相対URL]] なら[[絶対URL]] に[[解決]]した上で、[[文字列]]として[[比較]]する
- [27] 与えられた [[IRI]] を [[URI]] にした上で、[[文字列]]として[[比較]]する
- [28] 与えられた [[URL]] を[[バイト列]]として比較する

[29] 普通は >>25 だろう、と思えるかもしれませんが、規定をよく読むと比較演算への入力が元々の入力そのものではなく[[解決]]後の
[[URL]] だったり、[[RFC 3986]] [[URI]] 上の演算として定義されていたりするので注意が必要です。

[30] 普通は仕様上は[[文字列]]に対して比較が定義されていますが、現実の実装はしばしば[[バイト列]]に対して比較が実装されていたりして、
[[非ASCII文字]]が含まれる時に結果が変わってしまうことがあるので、やはり注意が必要です。

[FIG(short list)[ [51] 単純な[[文字列の比較]]
- [[XML名前空間URL]]
- [CODE[tag:]]
]FIG]

* URL 記録の比較

[45] 次の[[比較演算]]は、 [[URL記録]]について定義されています。つまり
[[URL構文解析器]]で [[URL]] としての基本的な[[正準化]]がなされた結果に対して[[比較]]するものです。
[FIG(list)[
- [46] [[素片識別子]]以外の全部分の[[比較]]
-- [8] [[フレーム]]読み込み
-- [[navigate]] から[[素片識別子へのnavigate]] に移るか否か
-- [CODE(DOMm)@en[pushState]]/[CODE(DOMm)@en[replaceState]] を認めるか否か
- [47] [[scheme][URL scheme]] と [[authority]] の[[比較]]
-- [17] [CODE(DOMm)@en[[[pushState]]]]/[CODE(DOMm)@en[[[replaceState]]]] を認めるか否か
]FIG]

* URL scheme にあまり依存しない比較・正規化

[FIG(list)[
- [7] [[navigate]] アルゴリズム中の [[AppCache]] の処理では、
先頭部分の完全一致の比較が行われます。 (ただし予め [[URL]] の[[構文解析]]に伴う[[正準化]]が行われた状態です。)
- [32] [[AtomにおけるURLの正規形]]
- [16] [[OAuthにおけるURLの正規化]]
]FIG]

* URL scheme に依存した比較・正規化

[FIG(list)[
- [31] [[HTTPにおけるURLの比較]]
- [33] [[SIPにおけるURLの比較]]
- [36] [CODE(URI)@en[[[msrp:]]]] / [CODE(URI)@en[[[msrps:]]]]
- [40] [[ハッシュ値URLの比較]]
- [CODE[[[uniformResourceIdentifier]]]]
- [CODE(URI)@en[[[pkcs11:]]]]
- [CODE(URI)@en[[[ws:]]]]/[CODE(URI)@en[[[wss:]]]]
]FIG]

[REFS[
- [35] [CITE[Widget Access Request Policy]] ([TIME[2012-02-04 04:00:27 +09:00]] 版) <http://dev.w3.org/2006/waf/widgets-access/#ta-case-insensitive-compare>
]REFS]

* 条件との比較

[13] [[URL]] と [[URL]] との[[比較]]ではなく、 [[URL]]
と[[URL]]の[[集合]]との[[比較]]が用いられることもあります。
詳しくは [[URLパターン]]も参照。

* 正準化とプロトコル処理

[48] [[要求対象]]の処理では、 [CODE[absolute-form]] の[[パス]]が[[空]]かどうかの判定が必要となる場合があります。

;; [CODE[absolute-form]] 参照。

* 歴史

[FIG(quote)[
[FIGCAPTION[
[41] RFC 2396 (URI) 6. URI Normalization and Equivalence
]FIGCAPTION]

> In many cases, different URI strings may actually identify the
identical resource. For example, the host names used in URL are
actually case insensitive, and the URL <http://www.XEROX.com> is
equivalent to <http://www.xerox.com>. In general, the rules for
equivalence and definition of a normal form, if any, are scheme
dependent. When a scheme uses elements of the common syntax, it will
also use the common syntax equivalence rules, namely that the scheme
and hostname are case insensitive and a URL with an explicit ":port",
where the port is the default for the scheme, is equivalent to one
where the port is elided.
]FIG]

* メモ

- [3] [[XML]] と関連仕様における URI の扱いについては [[XML//URI]] も参照して下さい。

[10]
[[RFC 4452]]: [CODE(URI)@en[[[info]]:]] [[URI]] の比較法

[12]

@@ [[SOAP]]: 応用依存


[20] [CITE[Wondering around: Java's URL little secret]]
([TIME[2009-08-29 10:34:46 +09:00]] 版)
<http://www.eishay.com/2008/04/javas-url-little-secret.html>

[21] [CITE[OWL 2 Web Ontology Language Structural Specification and Functional-Style Syntax]]
([TIME[2009-10-27 23:15:00 +09:00]] 版)
<http://www.w3.org/TR/2009/REC-owl2-syntax-20091027/#IRIs>

[34] [CITE@en[RFC 6021 - Common YANG Data Types]]
([TIME[2010-10-07 04:53:03 +09:00]] 版)
<http://tools.ietf.org/html/rfc6021>

[37] [CITE@en[RFC 6943 - Issues in Identifier Comparison for Security Purposes]]
( ([TIME[2013-11-19 01:20:54 +09:00]] 版))
<http://tools.ietf.org/html/rfc6943#section-3.3>

[38] [CITE@en[RDF 1.1 Concepts and Abstract Syntax]]
( ([TIME[2014-04-26 05:40:02 +09:00]] 版))
<https://dvcs.w3.org/hg/rdf/raw-file/default/rdf-concepts/index.html#dfn-iri-equality>

[39] [CITE@en[RFC 7252 - The Constrained Application Protocol (CoAP)]]
( ([TIME[2014-06-27 00:59:37 +09:00]] 版))
<http://tools.ietf.org/html/rfc7252#section-6.3>

[42] [CITE[IRC logs: freenode / #whatwg / 20140903]]
( ([TIME[2014-09-04 12:38:30 +09:00]] 版))
<http://krijnhoetmer.nl/irc-logs/whatwg/20140903#l-914>

[43] [CITE@en[Web Applications 1.0 r8739     Attempt to mitigate the injection elevation attack on appcache, and describe the attack in detail]]
( ([TIME[2014-09-04 06:39:00 +09:00]] 版))
<http://html5.org/r/8739>

[4] [[XRD]] は [[URL scheme]] 依存の[[正規化]]の規則により比較する [SRC[>>2]] としています。

[REFS[
- [2] [CITE[Extensible Resource Descriptor (XRD) Version 1.0]] ([TIME[2010-11-01 20:25:40 +09:00]] 版) <http://docs.oasis-open.org/xri/xrd/v1.0/xrd-1.0.html#element.subject>
]REFS]

[5] [CITE[Protocolv2Spec - google-safe-browsing - Client specification for the Google Safe Browsing v2.2 protocol - protect users from malicious web pages - Google Project Hosting]]
([TIME[2015-03-22 00:44:28 +09:00]] 版)
<https://code.google.com/p/google-safe-browsing/wiki/Protocolv2Spec#6.1._Canonicalization>

[6] [CITE@en[Phishing Protection: Server Spec - MozillaWiki]]
([TIME[2015-03-21 19:45:51 +09:00]] 版)
<https://wiki.mozilla.org/Phishing_Protection:_Server_Spec#Canonical_Hostname_Creation>

[FIG(quote)[
[FIGCAPTION[
[9] [CITE@en[RFC 7612 - Lightweight Directory Access Protocol (LDAP): Schema for Printer Services]]
([TIME[2015-07-01 10:20:12 +09:00]] 版)
<https://tools.ietf.org/html/rfc7612#section-1.4.2>
]FIGCAPTION]

>       These URI attributes specify EQUALITY matching with
>       'caseIgnoreMatch' (rather than with 'caseExactMatch') in order to
>       conform to the spirit of '''['''STD66''']''', which requires case-insensitive
>       matching on the host part of a URI versus case-sensitive matching
>       on the remainder of a URI.
>       These URI attributes follow existing practice of supporting
>       case-insensitive equality matching for host names in the
>       associatedDomain attribute defined in '''['''RFC4524''']'''.

]FIG]


[11] [CITE@en[Define URL equivalence. Fixes https://www.w3.org/Bugs/Public/show_bug… · whatwg/url@3f0bc8b]]
([TIME[2015-08-15 11:32:10 +09:00]] 版)
<https://github.com/whatwg/url/commit/3f0bc8b84d2f3bdb651207ce0f90c659c3a5a573>

[FIG(quote)[
[FIGCAPTION[
[14] [CITE@en[Model for Tabular Data and Metadata on the Web]]
([TIME[2015-12-03 19:28:42 +09:00]] 版)
<http://www.w3.org/TR/2015/REC-tabular-data-model-20151217/#h-url-normalization>
]FIGCAPTION]

> Metadata Discovery and Compatibility involve comparing URLs. When comparing URLs, processors must use Syntax-Based Normalization as defined in '''['''RFC3968''']'''. Processors must perform Scheme-Based Normalization for HTTP (80) and HTTPS (443) and should perform Scheme-Based Normalization for other well-known schemes.

]FIG]


[44] [CITE@en[Sniffly for ports.]]
([[mikewest]]著, [TIME[2016-07-07 15:31:29 +09:00]])
<https://github.com/w3c/webappsec-csp/commit/22d08b990290e49f5a666fad08de16d75bb369e7>

[49] [[はてなブックマーク]]は、登録される [[URL]] に独自の[[正規化]]を行っているようです。

[50] 例えば、[[素片識別子]]が[[空文字列]]の時、 [CODE[#]] ごと除去します。
