2021年12月12日

URL オブジェクト

組み込みの URL クラスは、URLを作成および解析するための便利なインターフェースを提供します。

厳密にURLオブジェクトを必要とするネットワークメソッドはありません。文字列で十分です。そのため、技術的にはURLを使用する必要はありません。しかし、時にそれは非常に役立ちます。

URLの作成

新しいURLオブジェクトを作成する構文

new URL(url, [base])
  • url – フルURLまたはパスのみ (ベースが設定されている場合、下記参照)、
  • base – オプションのベースURL: 設定され、url引数がパスのみを持つ場合、URLはbaseに対する相対で生成されます。

例:

let url = new URL('https://javascriptinfo.dokyumento.jp/profile/admin');

これら2つのURLは同じです

let url1 = new URL('https://javascriptinfo.dokyumento.jp/profile/admin');
let url2 = new URL('/profile/admin', 'https://javascriptinfo.dokyumento.jp');

alert(url1); // https://javascriptinfo.dokyumento.jp/profile/admin
alert(url2); // https://javascriptinfo.dokyumento.jp/profile/admin

既存のURLに対する相対パスに基づいて、新しいURLを簡単に作成できます。

let url = new URL('https://javascriptinfo.dokyumento.jp/profile/admin');
let newUrl = new URL('tester', url);

alert(newUrl); // https://javascriptinfo.dokyumento.jp/profile/tester

URLオブジェクトを使用すると、すぐにその構成要素にアクセスできるため、URLを解析するのに最適な方法です。例:

let url = new URL('https://javascriptinfo.dokyumento.jp/url');

alert(url.protocol); // https:
alert(url.host);     // javascript.info
alert(url.pathname); // /url

以下はURL構成要素のチートシートです

  • href はフルURLで、url.toString() と同じです
  • protocol はコロン文字 : で終わります
  • search – パラメータの文字列で、疑問符 ? から始まります
  • hash はハッシュ文字 # から始まります
  • HTTP認証がある場合は、user プロパティと password プロパティも存在する可能性があります: http://login:password@site.com (上記には描画されていません、めったに使用されません)。
文字列の代わりに、URLオブジェクトをネットワーク(およびほとんどの他の)メソッドに渡すことができます

fetchXMLHttpRequestURLオブジェクトを使用できます。URL文字列が期待されるほぼすべての場所で使えます。

一般的に、ほとんどのメソッドが文字列変換を実行し、URLオブジェクトをフルURLを持つ文字列に変換するため、URLオブジェクトは文字列の代わりに任意のメソッドに渡すことができます。

SearchParams “?…”

例えば、https://google.com/search?query=JavaScriptのように、特定の検索パラメータを持つURLを作成したいとしましょう。

URL文字列でそれらを提供できます。

new URL('https://google.com/search?query=JavaScript')

…しかし、スペースやラテン文字以外の文字などを含む場合、パラメータはエンコードする必要があります(詳細については下記を参照)。

そのため、URLプロパティ: url.searchParams, URLSearchParams 型のオブジェクトがあります。

これは検索パラメータのための便利なメソッドを提供します

  • append(name, value)nameでパラメータを追加,
  • delete(name)nameでパラメータを削除,
  • get(name)nameでパラメータを取得,
  • getAll(name) – 同じnameを持つすべてのパラメータを取得 (例えば、?user=John&user=Peteのようなことも可能です),
  • has(name)nameでパラメータの存在を確認,
  • set(name, value) – パラメータを設定/置換,
  • sort() – 名前でパラメータをソート。めったに必要とされない,
  • …そして、それはMapと同様に反復可能でもあります。

スペースと句読点を含むパラメータの例

let url = new URL('https://google.com/search');

url.searchParams.set('q', 'test me!'); // added parameter with a space and !

alert(url); // https://google.com/search?q=test+me%21

url.searchParams.set('tbs', 'qdr:y'); // added parameter with a colon :

// parameters are automatically encoded
alert(url); // https://google.com/search?q=test+me%21&tbs=qdr%3Ay

// iterate over search parameters (decoded)
for(let [name, value] of url.searchParams) {
  alert(`${name}=${value}`); // q=test me!, then tbs=qdr:y
}

エンコード

URLで使用が許可されている文字とそうでない文字を定義する標準のRFC3986があります。

許可されていない文字は、エンコードする必要があります。たとえば、ラテン文字以外の文字やスペースは、UTF-8コードに置き換えられ、%がプレフィックスとして付加されます。例えば、%20 (スペースは、歴史的な理由から+でエンコードできますが、例外です)。

朗報は、URLオブジェクトがすべてを自動的に処理してくれることです。エンコードされていないすべてのパラメータを提供し、URLを文字列に変換するだけです。

// using some cyrillic characters for this example

let url = new URL('https://ru.wikipedia.org/wiki/Тест');

url.searchParams.set('key', 'ъ');
alert(url); //https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D1%81%D1%82?key=%D1%8A

ご覧のとおり、URLパス内のТестとパラメータ内のъの両方がエンコードされています。

各キリル文字はUTF-8で2バイトで表現されるため、2つの%..エンティティがあり、URLが長くなりました。

文字列のエンコード

昔、URLオブジェクトが登場する前は、URLに文字列が使われていました。

現在、URLオブジェクトの方が便利なことが多いですが、文字列も引き続き使用できます。多くの場合、文字列を使用することでコードが短くなります。

ただし、文字列を使用する場合は、特殊文字を手動でエンコード/デコードする必要があります。

それのための組み込み関数があります

  • encodeURI – URL全体をエンコードします。
  • decodeURI – それをデコードして戻します。
  • encodeURIComponent – 検索パラメータやハッシュ、パス名などのURLコンポーネントをエンコードします。
  • decodeURIComponent – それをデコードして戻します。

自然な疑問は、「encodeURIComponentencodeURIの違いは何ですか?どちらをいつ使用する必要がありますか?」ということです。

上の図でコンポーネントに分割されているURLを見ると、簡単に理解できます

https://site.com:8080/path/page?p1=v1&p2=v2#hash

ご覧のとおり、:?=&#などの文字はURLで許可されています。

…一方で、検索パラメータなどの単一のURLコンポーネントを見ると、これらの文字はフォーマットを壊さないようにエンコードする必要があります。

  • encodeURI はURLで完全に禁止されている文字のみをエンコードします。
  • encodeURIComponent は、同じ文字をエンコードし、それに加えて、#, $, &, +, ,, /, :, ;, =, ? および @ の文字をエンコードします。

したがって、URL全体にはencodeURIを使用できます

// using cyrillic characters in url path
let url = encodeURI('http://site.com/привет');

alert(url); // http://site.com/%D0%BF%D1%80%D0%B8%D0%B2%D0%B5%D1%82

…一方、URLパラメータには代わりにencodeURIComponentを使用する必要があります

let music = encodeURIComponent('Rock&Roll');

let url = `https://google.com/search?q=${music}`;
alert(url); // https://google.com/search?q=Rock%26Roll

encodeURIと比較してください

let music = encodeURI('Rock&Roll');

let url = `https://google.com/search?q=${music}`;
alert(url); // https://google.com/search?q=Rock&Roll

ご覧のとおり、encodeURI&をエンコードしません。これはURL全体としては正当な文字だからです。

ただし、検索パラメータ内で&をエンコードする必要があります。そうしないと、q=Rock&Rollが得られます。これは実際にはq=Rockと、いくつかの不明瞭なパラメータRollです。意図したとおりではありません。

したがって、URL文字列に正しく挿入するには、各検索パラメータにencodeURIComponentのみを使用する必要があります。名前と値の両方をエンコードするのが最も安全です。許可された文字のみが含まれていると確信している場合を除きます。

URLと比較したエンコードの違い

クラスURLURLSearchParamsは最新のURI仕様に基づいています: RFC3986。一方、encode*関数は廃止されたバージョンRFC2396に基づいています。

いくつかの違いがあります。例えば、IPv6アドレスは異なる方法でエンコードされます

// valid url with IPv6 address
let url = 'http://[2607:f8b0:4005:802::1007]/';

alert(encodeURI(url)); // http://%5B2607:f8b0:4005:802::1007%5D/
alert(new URL(url)); // http://[2607:f8b0:4005:802::1007]/

ご覧のとおり、encodeURIは角括弧[...]を置き換えましたが、これは正しくありません。理由は、IPv6 urlがRFC2396(1998年8月)の時点では存在しなかったからです。

このようなケースはまれで、encode*関数はほとんどの場合、正常に動作します。

チュートリアルマップ

コメント

コメントする前にこれを読んでください…
  • 改善するための提案がある場合は、コメントする代わりにGitHub issueを送信するか、プルリクエストを送ってください。
  • 記事で理解できないことがある場合は、詳しく説明してください。
  • 数行のコードを挿入するには、<code>タグを使用し、複数行の場合は<pre>タグで囲みます。10行を超える場合は、サンドボックス(plnkrjsbincodepen…)を使用してください