JavaScriptでURLをホスト名とパスに解析するにはどうすればよいですか?


379

ひもをとりたい

var a = "http://example.com/aa/bb/"

そしてそれをオブジェクトに処理して

a.hostname == "example.com"

そして

a.pathname == "/aa/bb"

11
あなたは、現在のURLに取り組んでいる場合は、あなたがアクセスすることができますhostnameし、pathnameから直接locationオブジェクト。
rvighne 2014年

1
「lastPathPart」はどうですか?
ビクター

正規表現ではありませんが、Pythonモジュールtldextractはこれを正確に実行します:github.com/john-kurkowski/tldextract
Oliver Oliver

回答:


395

現代の方法:

new URL("http://example.com/aa/bb/")

プロパティを持つオブジェクトを返しますhostnamepathname一緒に、いくつかの他

最初の引数は相対または絶対URLです。相対の場合は、2番目の引数(ベースURL)を指定する必要があります。たとえば、現在のページに関連するURLの場合:

new URL("/aa/bb/", location)

ブラウザーに加えて、このAPIは v7以降、Node.jsでも使用できますrequire('url').URL


7
いいね!しかし、相対URLはそれを壊します... :( new URL('/stuff?foo=bar#baz')->SyntaxError: Failed to construct 'URL': Invalid URL
Lakenen '10年

56
実験的テクノロジー:IEはこれをサポートしていません!developer.mozilla.org/en-US/docs/Web/API/URL/...
cwouter

10
@cwouter:た​​だし、IEの代わりにEdgeで機能します
rvighne

4
これがそれを行う方法です、edgeはすでに3つのバージョンの上にあります。つまり、それは問題ではありません
Claudiu Creanga

7
JavaScriptが持っていないという事実は...かなり悲しい、内蔵のブラウザまたはサーバー上で動作解析するURLへの道である
Skitterm

365
var getLocation = function(href) {
    var l = document.createElement("a");
    l.href = href;
    return l;
};
var l = getLocation("http://example.com/path");
console.debug(l.hostname)
>> "example.com"
console.debug(l.pathname)
>> "/path"

14
これはクロスブラウザ互換のソリューションですか?
cllpse

70
これは元の投稿者を助ける/答えるかもしれませんが、この答えはDOMに依存して動作するため、ブラウザでJS作業を行う人にのみ機能することに注意してください。
Adam Batkin、2009

4
工夫とともに、シンプルさの別の例。
Saeed Neamati

26
hrefが相対の場合、IEでは機能しません。l.hostnameは空になります。完全なURLのみを提供している場合、これは機能します。
Derek Prior

7
絶対URLを使用しても、IE(IE 11でテスト済み)の動作はChromeおよびFirefoxとは異なります。IE pathnameは先頭のスラッシュを削除しますが、他のブラウザは削除しません。したがって、ブラウザによっては、/pathまたはpathになります。
TrueWillは、2015

299

ここにあります:https : //gist.github.com/jlong​​/2428561

var parser = document.createElement('a');
parser.href = "http://example.com:3000/pathname/?search=test#hash";

parser.protocol; // => "http:"
parser.host;     // => "example.com:3000"
parser.hostname; // => "example.com"
parser.port;     // => "3000"
parser.pathname; // => "/pathname/"
parser.hash;     // => "#hash"
parser.search;   // => "?search=test"
parser.origin;   // => "http://example.com:3000"

11
現在のブラウザの場所の解析された部分だけを取得したい場合は、最初の2行がparser = location;次のようになり、以降のすべての行が機能することに注意してください。ちょうど今ChromeとIE9でそれを試しました。
Lee Meador 2013

9
またpathname、IEの先頭のスラッシュは含まれていません。図を行きます。:D
nevelis 14

3
IEの場合、「/」+ parser.pathnameを使用します
sbose

警告:(プロトコルなしで)href http:だけdomain.comを渡しても戻ります。これを使用してプロトコルが欠落しているかどうかを確認したかったので、追加できたのですが、http:を想定しているため、この目的で使用できませんでした。
Max Hodges 2014年

ホスト名には実際にはプロトコルが含まれています。Chromeの最新バージョンでテストします。
AndroidDev 2017

109

aタグの動作を模倣する正規表現を使用した簡単な関数を次に示します。

長所

  • 予測可能な動作(クロスブラウザーの問題なし)
  • DOMは必要ありません
  • 本当に短いです。

短所

  • 正規表現は少し読みにくい

-

function getLocation(href) {
    var match = href.match(/^(https?\:)\/\/(([^:\/?#]*)(?:\:([0-9]+))?)([\/]{0,1}[^?#]*)(\?[^#]*|)(#.*|)$/);
    return match && {
        href: href,
        protocol: match[1],
        host: match[2],
        hostname: match[3],
        port: match[4],
        pathname: match[5],
        search: match[6],
        hash: match[7]
    }
}

-

getLocation("http://example.com/");
/*
{
    "protocol": "http:",
    "host": "example.com",
    "hostname": "example.com",
    "port": undefined,
    "pathname": "/"
    "search": "",
    "hash": "",
}
*/

getLocation("http://example.com:3000/pathname/?search=test#hash");
/*
{
    "protocol": "http:",
    "host": "example.com:3000",
    "hostname": "example.com",
    "port": "3000",
    "pathname": "/pathname/",
    "search": "?search=test",
    "hash": "#hash"
}
*/

編集:

これが正規表現の内訳です

var reURLInformation = new RegExp([
    '^(https?:)//', // protocol
    '(([^:/?#]*)(?::([0-9]+))?)', // host (hostname and port)
    '(/{0,1}[^?#]*)', // pathname
    '(\\?[^#]*|)', // search
    '(#.*|)$' // hash
].join(''));
var match = href.match(reURLInformation);

4
相対URLでは機能しません。正規表現を作成するときに、RFC-3986に従いましたか?> getLocation( "// example.com/"); null> getLocation( "/ pathname /?search"); null> getLocation( "/ pathname /"); null> getLocation( "relative"); null
2014年

2
私はこれがDOMを使用しない方法が好きですが、gregersには良い点があります。これが相対パスを処理できると便利です。空白を埋めてコードを追加するには、window.location(要素)を使用する必要があります。その場合、メソッドは偽善的になります。代替手段がない限り、これを完全に解決する方法がわかりません。
ターボ

元のURLでhrefキーを追加しました。これにより、dom実装でその戻りオブジェクトに一貫性が提供されます。
mattdlockyer 2017

2
誰かが相対URLを解析する必要がある場合、ここに更新された正規表現があります:/ ^(?:( https?\:)\ / \ /)?(([^:\ /?#] *)(?:\:([0 -9] +))?)([\ /] {0,1} [^?#] *)(\?[^#] * |)(#。* |)$ /
shlensky 2018

75
var loc = window.location;  // => "http://example.com:3000/pathname/?search=test#hash"

currentUrlを返します。

独自の文字列をURLとして渡したい場合(IE11では機能しません):

var loc = new URL("http://example.com:3000/pathname/?search=test#hash")

その後、次のように解析できます。

loc.protocol; // => "http:"
loc.host;     // => "example.com:3000"
loc.hostname; // => "example.com"
loc.port;     // => "3000"
loc.pathname; // => "/pathname/"
loc.hash;     // => "#hash"
loc.search;   // => "?search=test"

60

freddiefujiwaraの答えはかなり良いですが、Internet Explorer内で相対URLをサポートする必要もありました。私は次の解決策を思いつきました:

function getLocation(href) {
    var location = document.createElement("a");
    location.href = href;
    // IE doesn't populate all link properties when setting .href with a relative URL,
    // however .href will return an absolute URL which then can be used on itself
    // to populate these additional fields.
    if (location.host == "") {
      location.href = location.href;
    }
    return location;
};

これを使用して、必要なプロパティを取得します。

var a = getLocation('http://example.com/aa/bb/');
document.write(a.hostname);
document.write(a.pathname);

JSFiddleの例:http ://jsfiddle.net/6AEAB/


4
これは受け入れられる答えになるはずです。相対URLと絶対URLの処理の非常に巧妙な使用。+1
L0j1k 2014年

どうやらない初めてJSFiddleリンクは死んだ:stackoverflow.com/questions/25179964/...
サンタクロース

3
これはうまくいきましたが、他の人を助けることを望んでいる1つの更新がありました。これを使用してpostMessageリクエストのオリジンを確認しています。ポートがデフォルトポート(80または443)の場合、パスに追加されません。私はURLを作成するときに条件付きでチェックしました: var locationHost = (location.port !== '80' && location.port !== '443') ? location.host : location.hostname; var locationOrigin = location.protocol + '//' + locationHost;
rhoster

2
私はこのソリューションのより人気のあるバリアントについて他の場所でこのコメントをしましたが、これは私のお気に入りのソリューションだったので、ここで繰り返します。IE11では、hrefにユーザー名があると、これらすべてのプロパティの読み取りでセキュリティエラーがスローされます。例:「example.com」は問題なく機能します。しかし、「username@www.example.com」または「username:password@www.example.com」は、アンカー要素(例:ハッシュ)の他のプロパティのいずれかを参照しようとして失敗し、不愉快なエラーをスローします。
Clippy、

17

js-uri(Google Codeで利用可能)は文字列URLを受け取り、それからURIオブジェクトを解決します。

var some_uri = new URI("http://www.example.com/foo/bar");

alert(some_uri.authority); // www.example.com
alert(some_uri);           // http://www.example.com/foo/bar

var blah      = new URI("blah");
var blah_full = blah.resolve(some_uri);
alert(blah_full);         // http://www.example.com/foo/blah

ありがとう!!! uri = new Location( " example.com/aa/bb")typeof(window.location)== typeof(uri)
freddiefujiwara 2009

window.locationは文字列であるため、それがどのように可能または役立つのか、実際にはわかりません。簡単に変換できるのに、型が一致する必要があるのはなぜですか?
レックスM

developer.mozilla.org/en/DOM/window.locationは非常に素晴らしいAPIです!! 文字列をwindow.locationオブジェクトに変換することを願っています
freddiefujiwara '10 / 04/09

1
window.locationを設定するとブラウザーが変更されるため、このようなことが起こりません。
epascarello、2009

1
うーんそうです。window.locationは文字列ではありませんが、文字列から割り当てることができます。それを真似ることができるかどうかはわかりません。新しいURIオブジェクトに場所のプロトタイプを割り当てようとしましたが、うまくいきませんでした。
レックスM

12

単純な正規表現はどうですか?

url = "http://www.example.com/path/to/somwhere";
urlParts = /^(?:\w+\:\/\/)?([^\/]+)(.*)$/.exec(url);
hostname = urlParts[1]; // www.example.com
path = urlParts[2]; // /path/to/somwhere

のような有効なものを解析しよう//user:password@example.com/path/x?y=zとすると、単純な正規表現がそれをカットしない理由がわかります。無効なものを投げると、予測可能な方法で救済されるはずです。
ミッコランタライネン

単純な正規表現は単純な問題のためのものです:)しかし、このようなURLは正規表現では解析できないとは思えませんが、あと少し調整するだけで済みます。しかし、もっと複雑で弾丸のようなものが必要な場合は、おそらくいくつかのライブラリに行くでしょう。
svestka

12

今日、私はこの問題に遭遇し、次のことを発見しました:URL-MDN Web API

var url = new URL("http://test.example.com/dir/subdir/file.html#hash");

このリターン:

{ hash:"#hash", host:"test.example.com", hostname:"test.example.com", href:"http://test.example.com/dir/subdir/file.html#hash", origin:"http://test.example.com", password:"", pathname:"/dir/subdir/file.html", port:"", protocol:"http:", search: "", username: "" }

私の最初の貢献があなたを助けることを願っています!



6
ええ、でも一番上の男は2017年に彼のオーサーを更新するだけです。私は2016
。– A. Moynet 2018

ああ、私の悪い、申し訳ありません
マーティン・バンDriel

9

これは私がhttps://gist.github.com/1847816からコピーしたバージョンですが、読みやすくデバッグしやすいように書き直されました。アンカーデータを「result」という名前の別の変数にコピーする目的は、アンカーデータがかなり長いため、限られた数の値を結果にコピーすると、結果が単純になるためです。

/**
 * See: https://gist.github.com/1847816
 * Parse a URI, returning an object similar to Location
 * Usage: var uri = parseUri("hello?search#hash")
 */
function parseUri(url) {

  var result = {};

  var anchor = document.createElement('a');
  anchor.href = url;

  var keys = 'protocol hostname host pathname port search hash href'.split(' ');
  for (var keyIndex in keys) {
    var currentKey = keys[keyIndex]; 
    result[currentKey] = anchor[currentKey];
  }

  result.toString = function() { return anchor.href; };
  result.requestUri = result.pathname + result.search;  
  return result;

}

6

ブラウザー間のURL解析IE 6、7、8、9の相対パスの問題を回避します

function ParsedUrl(url) {
    var parser = document.createElement("a");
    parser.href = url;

    // IE 8 and 9 dont load the attributes "protocol" and "host" in case the source URL
    // is just a pathname, that is, "/example" and not "http://domain.com/example".
    parser.href = parser.href;

    // IE 7 and 6 wont load "protocol" and "host" even with the above workaround,
    // so we take the protocol/host from window.location and place them manually
    if (parser.host === "") {
        var newProtocolAndHost = window.location.protocol + "//" + window.location.host;
        if (url.charAt(1) === "/") {
            parser.href = newProtocolAndHost + url;
        } else {
            // the regex gets everything up to the last "/"
            // /path/takesEverythingUpToAndIncludingTheLastForwardSlash/thisIsIgnored
            // "/" is inserted before because IE takes it of from pathname
            var currentFolder = ("/"+parser.pathname).match(/.*\//)[0];
            parser.href = newProtocolAndHost + currentFolder + url;
        }
    }

    // copies all the properties to this object
    var properties = ['host', 'hostname', 'hash', 'href', 'port', 'protocol', 'search'];
    for (var i = 0, n = properties.length; i < n; i++) {
      this[properties[i]] = parser[properties[i]];
    }

    // pathname is special because IE takes the "/" of the starting of pathname
    this.pathname = (parser.pathname.charAt(0) !== "/" ? "/" : "") + parser.pathname;
}

使い方(デモJSFiddleはこちら):

var myUrl = new ParsedUrl("http://www.example.com:8080/path?query=123#fragment");

結果:

{
    hash: "#fragment"
    host: "www.example.com:8080"
    hostname: "www.example.com"
    href: "http://www.example.com:8080/path?query=123#fragment"
    pathname: "/path"
    port: "8080"
    protocol: "http:"
    search: "?query=123"
}

5

IE、Firefox、およびChromeで動作する最新のソリューションをお探しの場合:

ハイパーリンク要素を使用するこれらのソリューションは、Chromeでは同じように機能しません。無効な(または空白の)URLをChromeに渡すと、スクリプトの呼び出し元のホストが常に返されます。つまり、IEでは空白になりますが、Chromeではlocalhost(またはその他)になります。

リファラーを見ようとしているなら、これはだまされています。これを処理するために、返されるホストが元のURLにあったことを確認する必要があります。

    function getHostNameFromUrl(url) {
        // <summary>Parses the domain/host from a given url.</summary>
        var a = document.createElement("a");
        a.href = url;

        // Handle chrome which will default to domain where script is called from if invalid
        return url.indexOf(a.hostname) != -1 ? a.hostname : '';
    }

これは考慮すべき非常に重要なことです!
2rs2ts 2013

ただし、これは相対URLを完全に壊します!
Lakenen 2014年

4

AngularJSの方法-ここでフィドル:http : //jsfiddle.net/PT5BG/4/

<!DOCTYPE html>
<html>
<head>
    <title>Parse URL using AngularJS</title>
</head>
<body ng-app ng-controller="AppCtrl" ng-init="init()">

<h3>Parse URL using AngularJS</h3>

url: <input type="text" ng-model="url" value="" style="width:780px;">

<ul>
    <li>href = {{parser.href}}</li>
    <li>protocol = {{parser.protocol}}</li>
    <li>host = {{parser.host}}</li>
    <li>hostname = {{parser.hostname}}</li>
    <li>port = {{parser.port}}</li>
    <li>pathname = {{parser.pathname}}</li>
    <li>hash = {{parser.hash}}</li>
    <li>search = {{parser.search}}</li>
</ul>

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.min.js"></script>

<script>
function AppCtrl($scope) {

    $scope.$watch('url', function() {
        $scope.parser.href = $scope.url;
    });

    $scope.init = function() {
        $scope.parser = document.createElement('a');
        $scope.url = window.location;
    }

}
</script>

</body>
</html>

2
あなたがサービスを使用する場合、それはより角度のあるものに$documentなり$windowます
Cherniv '28

3

モジュールパターンを使用したシンプルで堅牢なソリューション。これにはIEの修正が含まれ、にpathnameは常に先行スラッシュ(/)がありません。

より動的なパーサーを提供するJSFiddleとともにGistを作成しました。ぜひチェックして、フィードバックをお寄せください。

var URLParser = (function (document) {
    var PROPS = 'protocol hostname host pathname port search hash href'.split(' ');
    var self = function (url) {
        this.aEl = document.createElement('a');
        this.parse(url);
    };
    self.prototype.parse = function (url) {
        this.aEl.href = url;
        if (this.aEl.host == "") {
           this.aEl.href = this.aEl.href;
        }
        PROPS.forEach(function (prop) {
            switch (prop) {
                case 'hash':
                    this[prop] = this.aEl[prop].substr(1);
                    break;
                default:
                    this[prop] = this.aEl[prop];
            }
        }, this);
        if (this.pathname.indexOf('/') !== 0) {
            this.pathname = '/' + this.pathname;
        }
        this.requestUri = this.pathname + this.search;
    };
    self.prototype.toObj = function () {
        var obj = {};
        PROPS.forEach(function (prop) {
            obj[prop] = this[prop];
        }, this);
        obj.requestUri = this.requestUri;
        return obj;
    };
    self.prototype.toString = function () {
        return this.href;
    };
    return self;
})(document);

デモ

出力

{
 "protocol": "https:",
 "hostname": "www.example.org",
 "host": "www.example.org:5887",
 "pathname": "/foo/bar",
 "port": "5887",
 "search": "?a=1&b=2",
 "hash": "section-1",
 "href": "https://www.example.org:5887/foo/bar?a=1&b=2#section-1",
 "requestUri": "/foo/bar?a=1&b=2"
}
{
 "protocol": "ftp:",
 "hostname": "www.files.com",
 "host": "www.files.com:22",
 "pathname": "/folder",
 "port": "22",
 "search": "?id=7",
 "hash": "",
 "href": "ftp://www.files.com:22/folder?id=7",
 "requestUri": "/folder?id=7"
}


3

なぜそれを使わないのですか?

        $scope.get_location=function(url_str){
        var parser = document.createElement('a');
        parser.href =url_str;//"http://example.com:3000/pathname/?search=test#hash";
        var info={
            protocol:parser.protocol,   
            hostname:parser.hostname, // => "example.com"
            port:parser.port,     // => "3000"
            pathname:parser.pathname, // => "/pathname/"
            search:parser.search,   // => "?search=test"
            hash:parser.hash,     // => "#hash"
            host:parser.host, // => "example.com:3000"      
        }
        return info;
    }
    alert( JSON.stringify( $scope.get_location("http://localhost:257/index.php/deploy/?asd=asd#asd"),null,4 ) );

3

Locutusプロジェクト(以前のphp.js)のparse_url()関数を使用することもできます。

コード:

parse_url('http://username:password@hostname/path?arg=value#anchor');

結果:

{
  scheme: 'http',
  host: 'hostname',
  user: 'username',
  pass: 'password',
  path: '/path',
  query: 'arg=value',
  fragment: 'anchor'
}


@StanQuinn、それはphp.jsがその名前をLocutusに変更したためです。新しいリンクで回答を更新しました。
Andrey Rudenko 2018年

3
function parseUrl(url) {
    var m = url.match(/^(([^:\/?#]+:)?(?:\/\/((?:([^\/?#:]*):([^\/?#:]*)@)?([^\/?#:]*)(?::([^\/?#:]*))?)))?([^?#]*)(\?[^#]*)?(#.*)?$/),
        r = {
            hash: m[10] || "",                   // #asd
            host: m[3] || "",                    // localhost:257
            hostname: m[6] || "",                // localhost
            href: m[0] || "",                    // http://username:password@localhost:257/deploy/?asd=asd#asd
            origin: m[1] || "",                  // http://username:password@localhost:257
            pathname: m[8] || (m[1] ? "/" : ""), // /deploy/
            port: m[7] || "",                    // 257
            protocol: m[2] || "",                // http:
            search: m[9] || "",                  // ?asd=asd
            username: m[4] || "",                // username
            password: m[5] || ""                 // password
        };
    if (r.protocol.length == 2) {
        r.protocol = "file:///" + r.protocol.toUpperCase();
        r.origin = r.protocol + "//" + r.host;
    }
    r.href = r.origin + r.pathname + r.search + r.hash;
    return m && r;
};
parseUrl("http://username:password@localhost:257/deploy/?asd=asd#asd");

絶対URLと相対URLの両方で機能します


abc://username:password@example.com:123/path/data?key=value&key2=value2#fragid1
山茶树和葡萄树

@山茶树和葡萄树userinfoサブコンポーネントを適切に処理するようにコードを更新しました。あなたのコメントをありがとう、私は前にその問題に気づかなかった
Nikolay

この正規表現が大好き
Kunal

2

ホイールの再発明をやめる。https://github.com/medialize/URI.js/を使用します

var uri = new URI("http://example.org:80/foo/hello.html");
// get host
uri.host(); // returns string "example.org:80"
// set host
uri.host("example.org:80");

5
問題を解決したいときはいつでも...ライブラリを使用しますか?OK ...(not)
jiminikiz

4
常にではない(実際にはほとんど決してない)が、URLは解析が非常に難しいため、RFCには多くの詳細があります。数千人が使用およびテストしたライブラリを使用する方が良い。
Hugo Sequeira、2015年

ライブラリで他の誰かにホイールを再発明させるのではなく、組み込みのものを使用するのはどうですか?stackoverflow.com/a/24006120/747739を
Phil

組み込み関数のIE11サポートがないため、このライブラリは優れています。ライブラリを使用しないと言うのは、jQueryを使用してはならず、ネイティブコードを記述するだけだと言っているようなものです。すべての開発者には異なるユースケースがあり、「最善の」方法はありません。バニラ/ネイティブが最もうまく機能する場合もあれば、そうでない場合もあります。開発者の92%がまだ学習する必要があります。
tno2007

1

url.jsライブラリを使用するだけです(webおよびnode.js用)。

https://github.com/websanova/js-url

url: http://example.com?param=test#param=again

url('?param'); // test
url('#param'); // again
url('protocol'); // http
url('port'); // 80
url('domain'); // example.com
url('tld'); // com

etc...

1

最初の答えで簡単なハック

var getLocation = function(href=window.location.href) {
    var l = document.createElement("a");
    l.href = href;
    return l;
};

これは、引数なしでも現在のホスト名を把握するために使用できます getLocation()。hostnameは現在のホストを提供します

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.