JavaScript | |

JavaScriptでURLからいろいろ取得する

いまさら~だけど、改めて調べたら知らないこともあった。

  1. 現在のURLから取得
  2. 任意のURLを分解して取得
  3. クエリストリングをオブジェクトで取得
  4. ウェルノウンポートは取得できない?

現在のURLから取得

window.location からいろいろ取れる。

例えば、現在のURLが http://note.kiriukun.com:8080/aaaaa/wwwww?v=123#here だったら↓のようになる。

console.log( location.href );      // -> "http://hoge:piyo@note.kiriukun.com:8080/aaaaa/wwwww?v=123#here"
console.log( location.protocol );  // -> "http:"
console.log( location.host );      // -> "note.kiriukun.com:8080"
console.log( location.hostname );  // -> "note.kiriukun.com"
console.log( location.port );      // -> "8080"
console.log( location.pathname );  // -> "/aaaaa/wwwww"
console.log( location.search );    // -> "?v=123"
console.log( location.hash );      // -> "#here"
console.log( location.origin );    // -> "http://note.kiriukun.com:8080"

現在のURLをゴミ無し (ポート / クエリストリング ? / フラグメント識別子 # 無し) で取得したかったら↓こう。

var pureUrl = `${location.protocol}//${location.hostname}${location.pathname}`;
console.log(pureUrl);
// -> http://note.kiriukun.com/aaaaa/wwwww

任意のURLを分解して取得

window.location は現在のURLでしか使えない。好きなURLを分解する方法。

こちらの方法なら、URLにBasic認証のユーザーとパスワードが含まれてたら username / password として取得できる。

URLオブジェクトを使う

var url = new URL('http://hoge:piyo@note.kiriukun.com:8080/aaaaa/wwwww?v=123#here');

console.log( url.href );      // -> "http://hoge:piyo@note.kiriukun.com:8080/aaaaa/wwwww?v=123#here"
console.log( url.protocol );  // -> "http:"
console.log( url.username );  // -> "hoge"
console.log( url.password );  // -> "piyo"
console.log( url.host );      // -> "note.kiriukun.com:8080"
console.log( url.hostname );  // -> "note.kiriukun.com"
console.log( url.port );      // -> "8080"
console.log( url.pathname );  // -> "/aaaaa/wwwww"
console.log( url.search );    // -> "?v=123"
console.log( url.hash );      // -> "#here"
console.log( url.origin );    // -> "http://note.kiriukun.com:8080"

a要素を使う

MDNの Location のページのサンプルで見かけました。

var url = document.createElement('a');
url.href = 'http://hoge:piyo@note.kiriukun.com:8080/aaaaa/wwwww?v=123#here';

console.log( url.href );      // -> "http://hoge:piyo@note.kiriukun.com:8080/aaaaa/wwwww?v=123#here"
console.log( url.protocol );  // -> "http:"
console.log( url.username );  // -> "hoge"
console.log( url.password );  // -> "piyo"
console.log( url.host );      // -> "note.kiriukun.com:8080"
console.log( url.hostname );  // -> "note.kiriukun.com"
console.log( url.port );      // -> "8080"
console.log( url.pathname );  // -> "/aaaaa/wwwww"
console.log( url.search );    // -> "?v=123"
console.log( url.hash );      // -> "#here"
console.log( url.origin );    // -> "http://note.kiriukun.com:8080"

クエリストリングをオブジェクトで取得

URL.searchParams というのもあるが、対応してるブラウザが少ない。

自力でパースするなら↓こう。

function getSearchParams() {
	var params = {};
	var search = window.location.search.substr(1);
	if (search === '') {
		return params;
	}
	search.split('&').forEach(str => {
		var arr = str.split('=');
		if (arr[0] !== '') {
			params[arr[0]] = arr[1] !== undefined ? decodeURIComponent(arr[1]) : '';
		}
	});
	return params;
}

// URL末尾に ?a=%E3%81%82%E3%81%82%E3%81%82&b=&c&d=0&e=1&f=aaa がついてる場合
console.log(getSearchParams());
/* -> {
	a: "あああ"
	b: ""
	c: ""
	d: "0"
	e: "1"
	f: "aaa"
} */

Dropbox API v2でしか見たことないが、フラグメント識別子 (URLの#以降) に同じようなパラメータが入ってる場合でも、上記の関数の window.location.searchwindow.location.hash に変更すれば同様に取得できる。

ウェルノウンポートは取得できない?

これ書いてて気づいたんだけど、少なくともHTTP/HTTPS/FTPだと、ポート番号にウェルノウンポートが明示的に指定されてても取得できないっぽい。

以下はChrome (71.0.3578.98) で試した時の結果。どれもポート番号を変えると普通に取得できるんだけど。

HTTPでポート80番
var url = new URL('http://note.kiriukun.com:80');

console.log( url.href );      // -> http://note.kiriukun.com/
console.log( url.protocol );  // -> http:
console.log( url.host );      // -> note.kiriukun.com
console.log( url.port );      // -> 
console.log( url.origin );    // -> http://note.kiriukun.com
HTTPでポート443番
var url = new URL('https://note.kiriukun.com:443');

console.log( url.href );      // -> https://note.kiriukun.com/
console.log( url.protocol );  // -> https:
console.log( url.host );      // -> note.kiriukun.com
console.log( url.port );      // -> 
console.log( url.origin );    // -> https://note.kiriukun.com
FTPでポート21番
var url = new URL('ftp://note.kiriukun.com:211');

console.log( url.href );      // -> ftp://note.kiriukun.com/
console.log( url.protocol );  // -> ftp:
console.log( url.host );      // -> note.kiriukun.com
console.log( url.port );      // -> 
console.log( url.origin );    // -> ftp://note.kiriukun.com

HTTPとHTTPSに限っては、Edge (42.17134.1.0) のコンソールで同じコードを動かすと、3行目で「SCRIPT14: セキュリティの問題が発生しました。」というエラーが出てそもそも分解できなかった。

他のプロトコルはまだ試せてない。