【Node.js】URLの解析(「WHATWG URL」と「Legacy URL」)【2023年】

  • このエントリーをはてなブックマークに追加

Node.js v6.x以降でURL構造の分解は2種類の方法がある。
「WHATWG URL」と「Legacy URL」である。
この2つはURLの分解方法が違う。
新規開発では「WHATWG URL」を使うこと。
WHATWG URL:「WHATWG URL」は、Web Hypertext Application Technology Working Group(WHATWG)が定義したURL解析の仕様である。
Node.js独自に定めたURL解析の方法ではない。
Legacy URL:Node.js独自に定めたURL解析の方法である。
「WHATWG URL」はv7.0.0, v6.13.0で追加されて、v10.0.0でグローバルオブジェクトでクラスが利用できるようになった。
「WHATWG URL」はブラウザで使用されているものと同じである。
「Legacy URL」はNode.js v18.15.0で非推奨になっている。
環境が「node v18.15.0」、「npm v8.13.2」で次のコードを実行した。
2023年4月2日現在「node v18.15.0」で「WHATWG URL」を使ったらいいみたいだな。
今後変わるかもしれないが、「WHATWG URL」が最新のURL解析方法と覚えておく。


const url = 'https://user:pass@sub.example.com:8080/p/a/t/h?query=100&a=9#hash';
const myURL = new URL(url);
const whitespace = 2;
const result = [];
const names = [];

const result2 = [];
const names2 = [];

let stringLengthMax = 0;
let buf = ' ';
let blanks = '';

console.log("Node.js v6.x以降でURL構造の分解は2種類の方法がある。");
console.log("「WHATWG URL」と「Legacy URL」である。");
console.log("この2つはURLの分解方法が違う。");
console.log("新規開発では「WHATWG URL」を使うこと。");
console.log("「WHATWG URL」はブラウザで使用されているものと同じである。");
console.log("「Legacy URL」はNode.js v18.15.0で非推奨になっている。");

console.log("");
console.log("★WHATWG URL★");
console.log(myURL);
result.push(url);
result.push(myURL.href);
result.push(myURL.origin);
result.push(myURL.protocol);
result.push(myURL.username);
result.push(myURL.password);
result.push(myURL.host);
result.push(myURL.port);
result.push(myURL.hostname);
result.push(myURL.pathname);
result.push(myURL.hash);
result.push(myURL.search);

names.push("url");
names.push("href");
names.push("origin");
names.push("protocol");
names.push("username");
names.push("password");
names.push("host");
names.push("port");
names.push("hostname");
names.push("pathname");
names.push("hash");
names.push("search");

//names配列の中の文字列で最大長をstringLengthMaxに格納する。
names.forEach(t => {if(t.length > stringLengthMax) stringLengthMax = t.length;});

//bufに格納した文字列を「stringLengthMax + whitespace」回数分のコピーを含む新しい文字列を作る。
blanks = buf.repeat(stringLengthMax + whitespace);

//URLの解析結果を出す。
names.forEach((t, u) => (console.log(t + ':' + blanks.slice(t.length) + result[u])));

console.log("");

console.log("URLSearchParamsに含まれる値はforEach()メソッドで取り出し可能である。");
myURL.searchParams.forEach(function(value, key) {
  console.log(key + " = " + value);
});

console.log("");
console.log("★Legacy URL★");

const _url = require('url');
const q = _url.parse(url,true);
const qdata = q.query;

console.log(q);

result2.push(url);
result2.push(q.href);
result2.push(q.protocol);
result2.push(q.slashes);
result2.push(q.auth);
result2.push(q.host);
result2.push(q.port);
result2.push(q.hostname);
result2.push(q.pathname);
result2.push(q.hash);
result2.push(q.search);

names2.push("url");
names2.push("href");
names2.push("protocol");
names2.push("slashes");
names2.push("auth");
names2.push("host");
names2.push("port");
names2.push("hostname");
names2.push("pathname");
names2.push("hash");
names2.push("search");

//names配列の中の文字列で最大長をstringLengthMaxに格納する。
names2.forEach(t => {if(t.length > stringLengthMax) stringLengthMax = t.length;});

//bufに格納した文字列を「stringLengthMax + whitespace」回数分のコピーを含む新しい文字列を作る。
blanks = buf.repeat(stringLengthMax + whitespace);

//URLの解析結果を出す。
names2.forEach((t, u) => (console.log(t + ':' + blanks.slice(t.length) + result2[u])));

console.log("");

/*

Object.keys()メソッドは、オブジェクトのプロパティのキーを配列として返す。
ただし、Object.keys()メソッドによって返されるキーの順番は、プロパティの追加順や定義順ではなく、
実装に依存する。つまり、キーの取り出し順序は保証されない。
そのため、Object.keys()メソッドを使用してオブジェクトのキーを取得する際に、
キーの順番に依存する処理を行うべきではない。

*/
console.log("Object.keys()メソッドを使って、queryに含まれる値はforEach()メソッドで取り出し可能である。");
const keys = Object.keys(q.query);
keys.forEach((key) => console.log(key + " = " +qdata[key]));

console.log("");

/*

Object.entries()メソッドは、オブジェクトのプロパティを[key, value]の形式で持つ配列として返す。
ただし、Object.keys()メソッドによって返されるキーの順番は、プロパティの追加順や定義順ではなく、
実装に依存する。つまり、キーと値の取り出し順序は保証されない。
そのため、Object.values()メソッドを使用してオブジェクトのキーと値を取得する際に、
値の順番に依存する処理を行うべきではない。
それから、Object.entries()もES2017で導入された機能であるため、古い環境では利用できない可能性がある。

*/

console.log("Object.entries()メソッドを使って、queryに含まれる値はforEach()メソッドで取り出し可能である。");
const entries = Object.entries(q.query);
entries.forEach(([key, value]) => {console.log(`${key} = ${value}`);});

console.log("");

/*

Object.values()メソッドは、オブジェクトのプロパティの値を配列として返す。
ただし、Object.values()メソッドによって返される値の順番は、プロパティの追加順や定義順ではなく、
実装に依存する。つまり、値の取り出し順序は保証されない。
そのため、Object.values()メソッドを使用してオブジェクトの値を取得する際に、
値の順番に依存する処理を行うべきではない。

*/

console.log("Object.values()メソッドを使って、queryに含まれる値はforEach()メソッドで取り出し可能である。");
const value = Object.values(q.query);
value.forEach((value) => console.log("value = " +value));


実行結果は次の通りになる。


C:\node\sample3>node -v
v18.15.0

C:\node\sample3>npm -v
8.13.2

C:\node\test>node test4.js
Node.js v6.x以降でURL構造の分解は2種類の方法がある。
「WHATWG URL」と「Legacy URL」である。
この2つはURLの分解方法が違う。
新規開発では「WHATWG URL」を使うこと。
「WHATWG URL」はブラウザで使用されているものと同じである。
「Legacy URL」はNode.js v18.15.0で非推奨になっている。

★WHATWG URL★
URL {
  href: 'https://user:pass@sub.example.com:8080/p/a/t/h?query=100&a=9#hash',
  origin: 'https://sub.example.com:8080',
  protocol: 'https:',
  username: 'user',
  password: 'pass',
  host: 'sub.example.com:8080',
  hostname: 'sub.example.com',
  port: '8080',
  pathname: '/p/a/t/h',
  search: '?query=100&a=9',
  searchParams: URLSearchParams { 'query' => '100', 'a' => '9' },
  hash: '#hash'
}
url:       https://user:pass@sub.example.com:8080/p/a/t/h?query=100&a=9#hash
href:      https://user:pass@sub.example.com:8080/p/a/t/h?query=100&a=9#hash
origin:    https://sub.example.com:8080
protocol:  https:
username:  user
password:  pass
host:      sub.example.com:8080
port:      8080
hostname:  sub.example.com
pathname:  /p/a/t/h
hash:      #hash
search:    ?query=100&a=9

URLSearchParamsに含まれる値はforEach()メソッドで取り出し可能である。
query = 100
a = 9

★Legacy URL★
Url {
  protocol: 'https:',
  slashes: true,
  auth: 'user:pass',
  host: 'sub.example.com:8080',
  port: '8080',
  hostname: 'sub.example.com',
  hash: '#hash',
  search: '?query=100&a=9',
  query: [Object: null prototype] { query: '100', a: '9' },
  pathname: '/p/a/t/h',
  path: '/p/a/t/h?query=100&a=9',
  href: 'https://user:pass@sub.example.com:8080/p/a/t/h?query=100&a=9#hash'
}
url:       https://user:pass@sub.example.com:8080/p/a/t/h?query=100&a=9#hash
href:      https://user:pass@sub.example.com:8080/p/a/t/h?query=100&a=9#hash
protocol:  https:
slashes:   true
auth:      user:pass
host:      sub.example.com:8080
port:      8080
hostname:  sub.example.com
pathname:  /p/a/t/h
hash:      #hash
search:    ?query=100&a=9

Object.keys()メソッドを使って、queryに含まれる値はforEach()メソッドで取り出し可能である。
query = 100
a = 9

Object.entries()メソッドを使って、queryに含まれる値はforEach()メソッドで取り出し可能である。
query = 100
a = 9

Object.values()メソッドを使って、queryに含まれる値はforEach()メソッドで取り出し可能である。
value = 100
value = 9

c:\node\test>

Node.jsのurlモジュールを使うときは、WHATWG URL APIを使う | 楽しいだけで十分です (yinm.info) ExternalLink
Node.js API (url) – URL 文字列の解析と生成 | プログラマーズ雑記帳 (fc2.com) ExternalLink
Node.js 入門 ー演習しながら学ぶ基本クラスの使い方ー | Udemy ExternalLink

  • このエントリーをはてなブックマークに追加

SNSでもご購読できます。

コメントを残す

*