情報アイランド

「情報を制する者は世界を制す」をモットーに様々な情報を提供することを目指すブログです。現在はプログラミング関連情報が多めですが、投資関連情報も取り扱っていきたいです。

RFC3986を読みながらURLエンコードについて考えた

RFC3986はURIの仕様が記述されている文書ですが、パーセントエンコード(所謂URLエンコード)については2章に書かれています。

パーセントエンコードの正確な仕様を把握することを目的として2章を精読しましたので、記事として書き残しておこうと思います。

  1. Characters

RFC3986の2章はURIで使用できる文字について書かれています。その中でパーセントエンコードについても併せて書かれています。

The URI syntax provides a method of encoding data, presumably for the sake of identifying a resource, as a sequence of characters. The URI characters are, in turn, frequently encoded as octets for transport or presentation. This specification does not mandate any particular character encoding for mapping between URI characters and the octets used to store or transmit those characters. When a URI appears in a protocol element, the character encoding is defined by that protocol; without such a definition, a URI is assumed to be in the same character encoding as the surrounding text.

URIにはデータを文字列にエンコードする方法が用意されているとあります。実は、これがパーセントエンコードです。

そして、URIの文字列自体は、(少なくともコンピュータ上では)、普通の文字列がそうであるように、何らかの文字コードを使って表される訳ですが、使用すべき文字コードは特に定まっていません。

A URI is composed from a limited set of characters consisting of digits, letters, and a few graphic symbols. A reserved subset of those characters may be used to delimit syntax components within a URI while the remaining characters, including both the unreserved set and those reserved characters not acting as delimiters, define each component’s identifying data.

URIで使用できる文字は英数字と幾つかの記号のみです。

これらの文字は予約されているもの予約されていないものに大別されます。

予約されている文字はURIの構成要素の区切り文字として使用されることが想定されているものであり、予約されていない文字はURIの構成要素を記述するために使用されることが想定されているものです。

2.1. Percent-Encoding

2.1章はパーセントエンコードについて書かれています。

A percent-encoding mechanism is used to represent a data octet in a component when that octet’s corresponding character is outside the allowed set or is being used as a delimiter of, or within, the component. A percent-encoded octet is encoded as a character triplet, consisting of the percent character "%" followed by the two hexadecimal digits representing that octet’s numeric value. For example, "%20" is the percent-encoding for the binary octet "00100000" (ABNF: %x20), which in US-ASCII corresponds to the space character (SP). Section 2.4 describes when percent-encoding and decoding is applied.

パーセントエンコードはURIで使用できない文字を表すのに使用されるとあります。また、URIの構成要素の区切り文字や構成要素の内部における区切り文字(「within」の部分)として使用されている文字を表すのにも使用されるとあります。

URIの構成要素の内部における区切り文字というのは構成要素が更に幾つかの細かい構成要素に分解される場合における細かい構成要素を区切るための文字のことです。

パーセントエンコードは%の後にパーセントエンコードする文字の値を2桁の16進文字列として表したものを続けます。

pct-encoded = "%" HEXDIG HEXDIG
The uppercase hexadecimal digits ’A’ through ’F’ are equivalent to the lowercase digits ’a’ through ’f’, respectively. If two URIs differ only in the case of hexadecimal digits used in percent-encoded octets, they are equivalent. For consistency, URI producers and normalizers should use uppercase hexadecimal digits for all percent-encodings.

16進文字列においては大文字(AからF)を使用すべきです。

2.2. Reserved Characters

2.2章は予約されている文字について書かれています。

URIs include components and subcomponents that are delimited by characters in the "reserved" set. These characters are called "reserved" because they may (or may not) be defined as delimiters by the generic syntax, by each scheme-specific syntax, or by the implementation-specific syntax of a URI’s dereferencing algorithm. If data for a URI component would conflict with a reserved character’s purpose as a delimiter, then the conflicting data must be percent-encoded before the URI is formed.

予約されている文字はURIの構成要素(や構成要素を構成する細かい構成要素)の区切り文字として使用されることが想定されているということが改めて書かれています。

この区切り文字には3種類のものがあります。

1つ目はこの仕様で区切り文字として定められているものです。

2つ目はURIのスキームによって区切り文字として定められているものです。

3つ目は実装(具体的なシステム)によって区切り文字として定められているものです。

重要なのはこの仕様以外で区切り文字として定められているものが存在し得るということです。この仕様からだけではどの文字が実際に区切り文字として使用されていてどの文字が区切り文字としては使用されていないのかを判断することはできないということです。

逆に、この仕様以外で区切り文字を定める際には予約されている文字の中から選択しなければなりません。そのため、予約されている文字に関しては区切り文字になっている可能性が常に存在しますし、予約されていない文字に関しては区切り文字になっている可能性はないと断定できます。

ある構成要素において構成要素の区切り文字と同じ文字を構成要素自体を記述するのに使用することはできません。

これは、そうしてしまうとその文字が区切り文字なのか構成要素の一部の文字なのか分からなくなってしまうからで、そのような場合には構成要素を記述する際には文字にパーセントエンコードを施し、文字を区別しなければなりません。

reserved = gen-delims / sub-delims
gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
sub-delims = "!" / "$" / "&" / "’" / "(" / ")" / "*" / "+" / "," / ";" / "="

予約されている文字は下の18個です。

  • :
  • /
  • ?
  • #
  • [
  • ]
  • @
  • !
  • $
  • &
  • '
  • (
  • )
  • *
  • +
  • ,
  • ;
  • =

The purpose of reserved characters is to provide a set of delimiting characters that are distinguishable from other data within a URI. URIs that differ in the replacement of a reserved character with its corresponding percent-encoded octet are not equivalent. Percent-encoding a reserved character, or decoding a percent-encoded octet that corresponds to a reserved character, will change how the URI is interpreted by most applications. Thus, characters in the reserved set are protected from normalization and are therefore safe to be used by scheme-specific and producer-specific algorithms for delimiting data subcomponents within a URI.

ここまでで述べられていることが再度述べられているだけです。

A subset of the reserved characters (gen-delims) is used as delimiters of the generic URI components described in Section 3. A component’s ABNF syntax rule will not use the reserved or gen-delims rule names directly; instead, each syntax rule lists the characters allowed within that component (i.e., not delimiting it), and any of those characters that are also in the reserved set are "reserved" for use as subcomponent delimiters within the component. Only the most common subcomponents are defined by this specification; other subcomponents may be defined by a URI scheme’s specification, or by the implementation-specific syntax of a URI’s dereferencing algorithm, provided that such subcomponents are delimited by characters in the reserved set allowed within that component.

予約されている文字の一部はURIの構成要素の区切り文字として使用されますが、残りの予約されている文字はURIの構成要素を構成する細かい構成要素の区切り文字としてのみ使用されることが想定されています。

つまり、予約されている文字を区切り文字以外として使用することはできません

URI producing applications should percent-encode data octets that correspond to characters in the reserved set unless these characters are specifically allowed by the URI scheme to represent data in that component. If a reserved character is found in a URI component and no delimiting role is known for that character, then it must be interpreted as representing the data octet corresponding to that character’s encoding in US-ASCII.

ただし、URIのスキームによって区切り文字以外として使用できるものと定められている場合はこの限りではないとされています。

2.3. Unreserved Characters

2.3章は予約されていない文字について書かれています。

Characters that are allowed in a URI but do not have a reserved purpose are called unreserved. These include uppercase and lowercase letters, decimal digits, hyphen, period, underscore, and tilde.
unreserved = ALPHA / DIGIT / "-" / "." / "_" / "˜"

予約されていない文字は英数字と下の4個です。

  • -
  • .
  • _
  • ~

URIs that differ in the replacement of an unreserved character with its corresponding percent-encoded US-ASCII octet are equivalent: they identify the same resource. However, URI comparison implementations do not always perform normalization prior to comparison (see Section 6). For consistency, percent-encoded octets in the ranges of ALPHA (%41-%5A and %61-%7A), DIGIT (%30-%39), hyphen (%2D), period (%2E), underscore (%5F), or tilde (%7E) should not be created by URI producers and, when found in a URI, should be decoded to their corresponding unreserved characters by URI normalizers.

予約されていない文字はパーセントエンコードすべきではありません。

2.4. When to Encode or Decode

2.4章はどのような場合にパーセントエンコードを行うべきか書かれています。

Because the percent ("%") character serves as the indicator for percent-encoded octets, it must be percent-encoded as "%25" for that octet to be used as data within a URI. Implementations must not percent-encode or decode the same string more than once, as decoding an already decoded string might lead to misinterpreting a percent data octet as the beginning of a percent-encoding, or vice versa in the case of percent-encoding an already percent-encoded string.

%自体は予約されている文字ではありませんが(したがって、区切り文字としては使用できませんが)、パーセントエンコードされた文字を識別するための文字ですので、%自体をURIの構成要素を記述するために使用することはできません。そのため、%自体はパーセントエンコードの対象となります

結論

という訳で、何らかのデータからURIの構成要素を作成する場合には英数字と下の4個の文字以外については必ずパーセントエンコードを行わなければなりません。

  • -
  • .
  • _
  • ~
pizyumi
プログラミング歴19年のベテランプログラマー。業務システム全般何でも作れます。現在はWeb系の技術を勉強中。
スポンサーリンク

-web