Node.jsにおいてURL(Uniform Resource Locator)を適切に扱うことは、Webアプリケーション開発における最も基礎的かつ重要な要素の一つです。
2026年現在のNode.js(v26.2.0以降)では、従来のレガシーなAPIからWeb標準であるWHATWG URL APIへの完全な移行が推奨されています。
ネットワークを介したデータのやり取りが複雑化する中で、ブラウザとサーバーサイドで一貫したURL操作を行うことは、バグの抑制とセキュリティの向上に直結します。
本記事では、Node.jsのurlモジュールの基礎から、最新のWeb標準APIを用いた具体的な操作方法、そして移行時の注意点について詳しく解説します。
Node.jsにおけるURLモジュールの役割と現状
Node.jsのurlモジュールは、URL文字列の解析、構築、および変換を行うための標準機能を提供しています。
歴史的にNode.jsには、独自の「レガシーAPI(url.parseなど)」と、Webブラウザと共通の「WHATWG URL API」の2種類が存在してきました。
2026年時点では、レガシーAPIは非推奨(Deprecated)の扱いとなっており、新規開発において使用することは推奨されません。
現代的な開発では、グローバルに提供されているURLクラスを利用することが一般的となっています。
この移行の背景には、セキュリティ上の脆弱性を回避し、JavaScriptエコシステム全体でURLの解釈を一貫させるという強い目的があります。
WHATWG URL APIの基本操作
Node.jsでURLを操作する際の中心となるのが、URLオブジェクトです。
このオブジェクトを使用することで、複雑なURL文字列を構造化されたデータとして扱うことができます。
URLオブジェクトのインスタンス化
URLオブジェクトを作成するには、コンストラクタにURL文字列を渡します。
// WHATWG URL APIを使用したURLの解析
const myUrl = new URL('https://user:pass@example.com:8080/p/a/t/h?query=string#hash');
console.log(myUrl.protocol); // プロトコル
console.log(myUrl.hostname); // ホスト名
console.log(myUrl.port); // ポート番号
console.log(myUrl.pathname); // パス
console.log(myUrl.search); // クエリ文字列
https:
example.com
8080
/p/a/t/h
?query=string
相対パスを使用してURLを生成する場合は、第2引数にベースとなるURL(Base URL)を指定する必要があります。
// ベースURLを指定した相対パスの解決
const baseUrl = 'https://example.com/api/v1/';
const relativePath = 'users/123';
const fullUrl = new URL(relativePath, baseUrl);
console.log(fullUrl.href);
https://example.com/api/v1/users/123
URLオブジェクトの主要プロパティ
URLオブジェクトは、URLの各コンポーネントにアクセスするための便利なプロパティを保持しています。
| プロパティ名 | 説明 | 例 |
|---|---|---|
href | シリアル化された完全なURL文字列 | https://example.com/path?q=1 |
origin | URLのオリジン(プロトコル + ホスト + ポート) | https://example.com |
protocol | 末尾のコロンを含むプロトコルスキーム | https: |
hostname | ポート番号を含まないホスト名 | example.com |
port | ポート番号(デフォルトポートの場合は空文字列) | 8080 |
pathname | スラッシュから始まるパス部分 | /path |
searchParams | クエリパラメータを操作するためのURLSearchParamsオブジェクト | (オブジェクト) |
URLSearchParamsによるクエリパラメータの高度な操作
URLのクエリパラメータを操作する際、文字列を手動で連結するのはバグの原因となります。
URLオブジェクトのsearchParamsプロパティを使用することで、安全かつ直感的にパラメータの追加・変更・削除が行えます。
パラメータの取得と追加
const url = new URL('https://example.com/search');
// パラメータの追加
url.searchParams.append('page', '1');
url.searchParams.append('sort', 'desc');
// 同じキーで複数追加も可能
url.searchParams.append('filter', 'active');
url.searchParams.append('filter', 'recent');
console.log(url.href);
https://example.com/search?page=1&sort=desc&filter=active&filter=recent
パラメータの更新と削除
setメソッドを使用すると、既存の同名キーをすべて削除した上で、新しい値を設定します。
const url = new URL('https://example.com/search?q=nodejs&lang=ja');
// langパラメータを上書き
url.searchParams.set('lang', 'en');
// qパラメータを削除
url.searchParams.delete('q');
console.log(url.search);
?lang=en
レガシーAPI(url.parse)からの移行ガイド
かつてNode.jsで標準だったurl.parse()は、現在では使用を避けるべき「レガシーAPI」に分類されています。
レガシーAPIは、URLのパースロジックに特有の癖があり、特定の入力に対してセキュリティリスク(オープンリダイレクト脆弱性など)を引き起こす可能性が指摘されています。
移行すべきコードのパターン
以下のような従来のコードは、WHATWG URL APIへの書き換えが必要です。
// 旧来の書き方(非推奨)
const url = require('url');
const parsed = url.parse('https://example.com/path');
console.log(parsed.hostname);
これを次のように修正します。
// 新しい書き方(推奨)
// ブラウザ互換のため、require('url')なしでもURLクラスは利用可能
const parsed = new URL('https://example.com/path');
console.log(parsed.hostname);
動作の違いに関する注意点
レガシーAPIとWHATWG APIでは、微妙に挙動が異なるプロパティがあります。
例えば、レガシーAPIのsearchプロパティは「?」が含まれますが、WHATWG APIでも同様に「?」が含まれます。
しかし、「パスの一部としてのスラッシュ」の扱いや、特殊文字のエスケープ処理においてWHATWG APIの方が厳格です。
既存のシステムを移行する際は、パース後の文字列が厳密に一致するかどうかテストコードで確認することを強く推奨します。
ファイルパスとURLの相互変換
Node.js特有のユースケースとして、ローカルのファイルパスをURL形式(file://…)に変換したり、その逆を行ったりする場面があります。
特にECMAScript Modules(ESM)環境では、__dirnameや__filenameが利用できないため、import.meta.urlを処理するためにこれらの関数が重宝されます。
fileURLToPath と pathToFileURL
これらのユーティリティ関数は、node:urlモジュールからインポートして使用します。
import { fileURLToPath, pathToFileURL } from 'node:url';
import path from 'node:path';
// URLをファイルパスに変換
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
console.log(`ファイルパス: ${__filename}`);
// ファイルパスをURLに変換
const filePath = '/usr/bin/node';
const fileUrl = pathToFileURL(filePath);
console.log(`URL形式: ${fileUrl.href}`);
ファイルパス: /home/user/project/index.js
URL形式: file:///usr/bin/node
Windows環境とUNIX環境でのパス区切り文字の違い(\ と /)を正しく吸収してくれるため、OSに依存しないコードを書くために必須の知識です。
Node.js特有のユーティリティ関数
urlモジュールには、URLオブジェクト以外にも便利な関数が含まれています。
url.domainToASCII と url.domainToUnicode
国際化ドメイン名(IDN)を扱う際に使用されます。
日本語ドメインなどをPunycode形式に変換したり、その逆を行ったりすることができます。
import url from 'node:url';
const domain = '総務省.jp';
const asciiDomain = url.domainToASCII(domain);
console.log(asciiDomain);
const unicodeDomain = url.domainToUnicode(asciiDomain);
console.log(unicodeDomain);
xn--l8jtbt6z.jp
総務省.jp
url.format によるURLのシリアル化
オブジェクトからURL文字列を生成する際、url.format()を使用できます。
WHATWG URLオブジェクトを渡した場合は、単にurl.hrefを取得するのと同じ動作になりますが、オプションを指定してカスタマイズすることが可能です。
const myUrl = new URL('https://example.com/a?b=c');
const formatted = url.format(myUrl, { fragment: false, unicode: true });
console.log(formatted);
実務での活用とセキュリティ上の注意点
URL操作は一見単純に見えますが、外部からの入力を扱う場合には細心の注意が必要です。
例えば、ユーザーから提供されたURLへリダイレクトさせる処理を実装する場合、ホスト名のバリデーションを怠ると、フィッシングサイトへの誘導に悪用される恐れがあります。
バリデーションの例
特定のドメインのみを許可するホワイトリスト形式のチェックは、以下のように実装します。
function isSafeUrl(inputUrl) {
try {
const url = new URL(inputUrl);
const allowedHosts = ['example.com', 'api.example.com'];
// ホスト名が許可リストに含まれているか確認
return allowedHosts.includes(url.hostname);
} catch (e) {
// 不正な形式のURLはエラーになるため安全ではないと判断
return false;
}
}
console.log(isSafeUrl('https://example.com/dashboard'));
console.log(isSafeUrl('https://malicious-site.com/'));
true
false
new URL()は、不正な形式の文字列が渡された場合にTypeErrorをスローするため、必ずtry-catchブロックで囲むことが重要です。
また、プロトコルがhttps:であることの確認を組み合わせることで、より強固なセキュリティを確保できます。
まとめ
Node.jsにおけるURLモジュールは、Web標準APIへの準拠を完了し、より安全で移植性の高いツールへと進化しました。
2026年の開発においては、従来のurl.parse()を完全に卒業し、URLクラスおよびURLSearchParamsを活用することが標準的な作法となっています。
これらのAPIはブラウザのJavaScriptと共通であるため、フロントエンドとバックエンドでコードを共有したり、学習コストを削減したりするメリットもあります。
パス操作を行う際にはnode:pathだけでなく、fileURLToPathなどのURL変換ユーティリティを適切に組み合わせることを忘れないでください。
正確なURL処理の知識を身につけることは、堅牢なWebアプリケーションを構築するための第一歩です。
本記事で紹介したテクニックを活用し、一貫性のあるモダンなNode.js開発を推進していきましょう。
