JavaScript の URL API 入門:pathname・searchParams でURLを分解・組み立てる

スポンサーリンク

new URL() はブラウザ・Node.js・Deno で使える組み込みのURL解析クラスです。URLを文字列で扱うより安全で、パス・クエリ・ホスト名など各部分を簡単に取り出せます。

URLを分解する

const url = new URL('https://example.com/users/123?page=2&sort=desc#comments')

url.href       // 'https://example.com/users/123?page=2&sort=desc#comments'
url.protocol   // 'https:'
url.hostname   // 'example.com'
url.port       // '' (省略時は空文字)
url.pathname   // '/users/123'
url.search     // '?page=2&sort=desc'
url.hash       // '#comments'
url.origin     // 'https://example.com'

パスだけ取り出す

const url = new URL('https://example.com/users/123?page=2')
url.pathname  // '/users/123'

正規表現や split を使わずに確実にパスだけ取れます。

クエリパラメータを操作する(searchParams)

url.searchParamsURLSearchParams オブジェクトです。クエリ文字列を個別に読み書きできます。

取得

const url = new URL('https://example.com/search?q=javascript&page=2&sort=desc')

url.searchParams.get('q')       // 'javascript'
url.searchParams.get('page')    // '2'
url.searchParams.get('missing') // null(存在しないキー)
url.searchParams.has('q')       // true

全パラメータをループする

const url = new URL('https://example.com/?a=1&b=2&c=3')

for (const [key, value] of url.searchParams) {
  console.log(key, value)
}
// a 1
// b 2
// c 3

// オブジェクトに変換
const params = Object.fromEntries(url.searchParams)
// { a: '1', b: '2', c: '3' }

同じキーが複数ある場合

const url = new URL('https://example.com/?tag=js&tag=ts&tag=node')

url.searchParams.get('tag')     // 'js'(最初の1件)
url.searchParams.getAll('tag')  // ['js', 'ts', 'node'](全件)

追加・変更・削除

const url = new URL('https://example.com/search?q=hello')

url.searchParams.set('q', 'world')   // 上書き
url.searchParams.set('page', '1')    // 追加
url.searchParams.append('tag', 'js') // 同じキーで追加
url.searchParams.delete('page')      // 削除

url.href  // 'https://example.com/search?q=world&tag=js'

URLを組み立てる

ベースURLにパスを結合する

const base = 'https://api.example.com'
const url = new URL('/users/123', base)

url.href  // 'https://api.example.com/users/123'

クエリパラメータを付けてURLを作る

const url = new URL('https://api.example.com/search')
url.searchParams.set('q', 'JavaScript')
url.searchParams.set('page', '1')
url.searchParams.set('limit', '20')

url.href
// 'https://api.example.com/search?q=JavaScript&page=1&limit=20'

URLSearchParams 単体で使う

URL全体がなくてもクエリ文字列だけ操作できます。

// window.location.search からクエリを取得
const params = new URLSearchParams(window.location.search)
params.get('page')  // '2'

// オブジェクトから作る
const params = new URLSearchParams({ q: 'hello', page: '1' })
params.toString()   // 'q=hello&page=1'

よくある使い方

現在のページのパスを取得する(ブラウザ)

const url = new URL(window.location.href)
url.pathname  // '/users/123'

fetchのURLにクエリを動的に付ける

const endpoint = new URL('https://api.example.com/posts')
endpoint.searchParams.set('page', page)
endpoint.searchParams.set('limit', '20')
if (tag) endpoint.searchParams.set('tag', tag)

const res = await fetch(endpoint.href)

ログからURLのパスだけ抽出する

const logs = [
  'https://example.com/users/1?ref=top',
  'https://example.com/posts/42?page=2',
]

const paths = logs.map(href => new URL(href).pathname)
// ['/users/1', '/posts/42']

リダイレクト先が同じオリジンか確認する

function isSameOrigin(href) {
  try {
    const url = new URL(href)
    return url.origin === window.location.origin
  } catch {
    return false
  }
}

isSameOrigin('https://example.com/dashboard')  // true
isSameOrigin('https://evil.com/phishing')       // false

無効なURLは例外になる

new URL('not-a-url')
// TypeError: Failed to construct 'URL': Invalid URL

function parseUrl(href) {
  try {
    return new URL(href)
  } catch {
    return null
  }
}

まとめ

プロパティ / メソッド 内容
url.pathname パス部分(/users/123
url.hostname ホスト名(example.com
url.origin オリジン(https://example.com
url.search クエリ文字列(?q=hello
url.hash フラグメント(#section
url.searchParams.get(key) クエリパラメータを1件取得
url.searchParams.getAll(key) 同じキーの値を全件取得
url.searchParams.set(key, val) クエリパラメータをセット
url.searchParams.delete(key) クエリパラメータを削除
url.searchParams.has(key) クエリパラメータの存在確認

curlでAPIにリクエストを送る方法は「curl入門:GET・POST・PUT・認証・クッキーの使い方まとめ」を参照してください。