web-dev-qa-db-ja.com

URL文字列が絶対か相対かをテストする方法は?

JavascriptまたはjQueryの相対パスまたは絶対パスである場合、どのようにURLをテストできますか?渡されたURLがローカルパスであるか外部パスであるかに応じて、適切に処理したいと思います。

if (urlString starts with http:// or https://)
 //do this
60
TruMan1
var pat = /^https?:\/\//i;
if (pat.test(urlString))
{
    //do stuff
}

プロトコル相対URLには、次の正規表現を使用します。

/^https?:\/\/|^\/\//i

29
strah

速い

http://またはhttps://のみをテストする必要がある場合、最も効率的なの方法は次のとおりです。

if (urlString.indexOf('http://') === 0 || urlString.indexOf('https://') === 0)

ユニバーサル

ただし、より普遍的、大文字と小文字を区別しない、プロトコルに依存しないアプローチをお勧めします。

var r = new RegExp('^(?:[a-z]+:)?//', 'i');
r.test('http://example.com'); // true - regular http absolute URL
r.test('HTTP://EXAMPLE.COM'); // true - HTTP upper-case absolute URL
r.test('https://www.exmaple.com'); // true - secure http absolute URL
r.test('ftp://example.com/file.txt'); // true - file transfer absolute URL
r.test('//cdn.example.com/lib.js'); // true - protocol-relative absolute URL
r.test('/myfolder/test.txt'); // false - relative URL
r.test('test'); // false - also relative URL

RegExpを説明する

^(?:[a-z]+:)?//

^-文字列の始まり
(?:-キャプチャされていないグループの始まり
[a-z]+-「a」〜「z」の任意の文字を1回以上
:-文字列(コロン文字)
)?-キャプチャされていないグループの終わり。 0回または1回表示されるグループ
//-文字列(2つのスラッシュ文字)
'i'-大文字と小文字を区別しないフラグ

137
Geo

正規表現を使用します。

if (/^(?:[a-z]+:)?\/\//i.test(url))
17
SLaks

元の回答

非常にfastと非常にflexibleのチェックは:

_if (url.indexOf('://') > 0 || url.indexOf('//') === 0 ) {
    // URL is absolute; either "http://example.com" or "//example.com"
} else {
    // URL is relative
}
_

次の場合、これは絶対URLを認識します。

  • URLの最初の文字の後にafterの「://」が含まれている
  • URLは「//」で始まります(プロトコル相対)

  • 正規表現なし。
  • JQueryまたはその他の依存関係はありません。
  • 条件の大文字と小文字を区別するハードコーディングされたプロトコル名はありません。
  • 文字列操作なし(例:toLowerCaseなど)。
  • 「相対または絶対」のチェックのみで、他の健全性チェックは行いません。WebURLまたは内部プロトコルに使用できます。

更新1(全機能の例)

以下は、指定されたURLに対してtrue/falseを返すクイックfunctionです。

_function isUrlAbsolute(url) { 
    return (url.indexOf('://') > 0 || url.indexOf('//') === 0);
}
_

ES6でも同じです:

_const isUrlAbsolute = (url) => (url.indexOf('://') > 0 || url.indexOf('//') === 0)
_

更新2(URLパラメーター内のURL)

_/redirect?target=http://example.org_形式のURLを追加でアドレスするには、次のコードを使用することをお勧めします。

_function isUrlAbsolute(url) {
    if (url.indexOf('//') === 0) {return true;} // URL is protocol-relative (= absolute)
    if (url.indexOf('://') === -1) {return false;} // URL has no protocol (= relative)
    if (url.indexOf('.') === -1) {return false;} // URL does not contain a dot, i.e. no TLD (= relative, possibly REST)
    if (url.indexOf('/') === -1) {return false;} // URL does not contain a single slash (= relative)
    if (url.indexOf(':') > url.indexOf('/')) {return false;} // The first colon comes after the first slash (= relative)
    if (url.indexOf('://') < url.indexOf('.')) {return true;} // Protocol is defined before first dot (= absolute)
    return false; // Anything else must be relative
}
_

短い形式とES 6でも同じ

_// Traditional JS, shortened
function isUrlAbsolute(url) {
    return url.indexOf('//') === 0 ? true : url.indexOf('://') === -1 ? false : url.indexOf('.') === -1 ? false : url.indexOf('/') === -1 ? false : url.indexOf(':') > url.indexOf('/') ? false : url.indexOf('://') < url.indexOf('.') ? true : false;
}

// ES 6
const isUrlAbsolute = (url) => (url.indexOf('//') === 0 ? true : url.indexOf('://') === -1 ? false : url.indexOf('.') === -1 ? false : url.indexOf('/') === -1 ? false : url.indexOf(':') > url.indexOf('/') ? false : url.indexOf('://') < url.indexOf('.') ? true : false)
_

以下にテストケースを示します。

_// Test
console.log( isUrlAbsolute('http://stackoverflow.com') ) // -> true
console.log( isUrlAbsolute('//stackoverflow.com') ) // -> true
console.log( isUrlAbsolute('stackoverflow.com') ) // -> false
console.log( isUrlAbsolute('Ftp://example.net') ) // -> true
console.log( isUrlAbsolute('/redirect?target=http://example.org') ) // -> false
_

更新3(相対URLの明確化)

無効な出力に関するいくつかのコメントを見ました:

  • Solutionはlocalhostに対してfalseを返します
  • _http:example.com_で応答が失敗する

ただし、これらのURLは実際には相対URLです。テストは簡単です:

  1. Localhost(ウェブルート)にいくつかのフォルダーを作成します。たとえば、_a/b/c/_
  2. Index.htmlファイルを作成し、次のリンクを配置します:_<a href="localhost">test</a>_
  3. ブラウザでインデックスページを開きます。 http://localhost/a/b/c/index.html をクリックし、リンクをクリックします。 http:// localhost/a/b/c/localhost で終了します( http:// localhost では終了しません)
  4. リンク_http:example.com_をindex.htmlファイルに配置する場合も同様です。 http://example.com ではなく http://localhost/a/b/c/example.com で終了します
14
Philipp

現在、多くのサービスが protocol-relative URL (eg。// cdn.example.com/libary.js)、このメソッドはより安全です:

var isAbsolute = new RegExp('^([a-z]+://|//)', 'i');

if (isAbsolute.test(urlString)) {
  // go crazy here
}
9
rgtk

さらにユニバーサルなRFC準拠のURIアプローチ:

_(?:^[a-z][a-z0-9+.-]*:|\/\/)_ 正規表現の説明

ここにリストされている他のソリューションは、_mailto:[email protected]_のようなリンクでは失敗します

RFC 3986では、Schemeを次のように定義しています:

scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )

3.1。スキームhttps://tools.ietf.org/html/rfc3986#section-3.1

プロトコル相対URLはセクション4.2で技術的に有効ですが、Paul Irishは別の方法で振り返り、これをアンチパターンと見なしています。 http://www.paulirish.com/2010/the-protocol-relative-url/ を参照してください

4.2。相対参照http://tools.ietf.org/html/rfc3986#section-4.2

プロトコル相対URLを使用しない正規表現が必要な場合:

_^[a-z][a-z0-9+.-]*:_

他のタイプの有効なURIエッジケースの完全なリストを確認するには、こちらのリストをご覧ください: https://en.wikipedia.org/wiki/URI_scheme

8
Evan

正規表現などの低レベルのものを使用しないでください。これらのことは他の多くの人々によって解決されています。特にエッジケース。

RI.js を見てください、それは仕事をするはずです: http://medialize.github.io/URI.js/docs.html#is

var uri = new URI("http://example.org/");
uri.is("absolute") === true;
5
koppor
var external = RegExp('^(https?:)?//');
if(external.test(el)){
    // do something
}

編集:

次の正規表現を使用すると、リンクが同じドメインに移動するか、外部ドメインに移動するかを確認できます。

var external = RegExp('^((f|ht)tps?:)?//(?!' + location.Host + ')');
if(external.test(el)){
    // do something
}
5
davids

ニーズに応じて、これを判断するより信頼性の高い方法は、 built-in URL interface を使用して、2つのURLオブジェクトを構築し、発信元を比較することだと思います。

new URL(document.baseURI).Origin === new URL(urlToTest, document.baseURI).Origin;

これにより、ブラウザはEdgeケースの副作用を心配することなく、このすべてを解析して把握できます。

2
Brad

次の関数は、ハイパーリンク上でクリックが発生したときに呼び出されます。つまり、タグにURLが含まれる場合は「a」タグが相対的であるか、同じホストが含まれている場合、異なるURLが含まれている場合はその新しいページが同じブラウザータブに読み込まれ、ページが読み込まれます新しいブラウザタブ

jQuery(document).ready(function() {
    $('a').click(function(){

        var a = this;
        var a_href = $(this).attr('href');
        var regex = new RegExp('^(?:[a-z]+:)?//', 'i');     

        if(a.Host == location.Host || regex.test(a_href) == false){
            a.target = '_self';
        }else{
            a.target = '_blank';
        }
    }); 
});
1
Prajyot
var adress = 'http://roflmao.com';
if (adress.substr(0,7) == 'http://' || adress.substr(0,8) == 'https://') {
    //
}
1
OptimusCrime

問題への防弾アプローチは次のとおりです。

ブラウザがすべてを処理するようにします。複雑でエラーが発生しやすい正規表現は必要ありません。

const isAbsoluteUrl = (url) => {
  const link = document.createElement('a');
  link.href = url;
  return link.Origin + link.pathname + link.search + link.hash === url;
};

残念ながら、nodejs環境では機能しません。

1
Etienne Martin