JavaScript文字列がURLかどうかを確認する


283

JavaScriptで文字列がURLかどうかを確認する方法はありますか?

URLはのように書かれている可能性が高いため、RegExesは除外されますstackoverflow。それはそれは持っていないかもしれないということである.comwwwまたはhttp


22
がない場合http、デフォルトではURLはありません。
nfechner

1
@nfechnerは、プロトコルを指定せずにコロン文字を使用する場合(できれば次の2つのフォワードスラッシュを使用)、URLではないことを示しています。
jcolebrand 2011

5
URL RFCで読み取れるように、文字列を有効なURLにするために実際に必要なのはコロンだけです。:有効なURLは次のようになり<scheme>:<scheme-specific-part>
nfechner


8
どのように何かがURLであるかどうかをテストすることで、高コンテキスト依存し、さらに資格のない、あまりにも漠然としました。URL RFC仕様に準拠しているか、OSシステムコールを実行してURLを開くhrefときに機能window.open(url)するか、アンカー要素としてとして解析されるか、呼び出し時に機能するか、実際に存在するものをポイントし、ブラウザーの場所で機能するかどうかは重要ですか?バー、または上記の組み合わせ?どれを気にするかによって、非常に異なる答えが得られます。
ロイティンカー

回答:


189

回答のある関連質問:

JavaScript正規表現URLマッチング

または、Devshedからのこの正規表現

function validURL(str) {
  var pattern = new RegExp('^(https?:\\/\\/)?'+ // protocol
    '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|'+ // domain name
    '((\\d{1,3}\\.){3}\\d{1,3}))'+ // OR ip (v4) address
    '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*'+ // port and path
    '(\\?[;&a-z\\d%_.~+=-]*)?'+ // query string
    '(\\#[-a-z\\d_]*)?$','i'); // fragment locator
  return !!pattern.test(str);
}

1
私は知っていますが、ブックマークを検索しています。ブックマークのほとんどは、stackoverflow(.comなどなし)のように書かれています
Bruno

3
@Bruno:それは非常に可能性が高い彼らは、内部で別のタイトルとURLを保存していることだ、のような{ title: "Stackoverflow", uri: "http://stackoverflow.com" } アップデート:確かに、参照code.google.com/chrome/extensions/bookmarks.html
マルセルKorpel

10
あなたの例を使用しようとしています。しかし、Firebugでエラーが発生していますinvalid quantifier。何か案が?
Sisir

125
関数の戻り値:SyntaxError: Invalid regular expression: /^(https?://)?((([a-zd]([a-zd-]*[a-zd])*).)+[a-z]{2,}|((d{1,3}.){3}d{1,3}))(:d+)?(/[-a-zd%_.~+]*)*(?[;&a-zd%_.~+=-]*)?(#[-a-zd_]*)?$/: Invalid group Google Chrome(バージョン30.0.1599.101)(Mac OS X:10.8.5)
dr.dimitru 2013年

10
文字列をパラメータとして使用する場合RegExp、バックスラッシュをダブルエスケープする必要があることに注意してください。そうしないと、無効なグループなどのエラーが発生します
Kjell

165
function isURL(str) {
  var pattern = new RegExp('^(https?:\\/\\/)?'+ // protocol
  '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.?)+[a-z]{2,}|'+ // domain name
  '((\\d{1,3}\\.){3}\\d{1,3}))'+ // OR ip (v4) address
  '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*'+ // port and path
  '(\\?[;&a-z\\d%_.~+=-]*)?'+ // query string
  '(\\#[-a-z\\d_]*)?$','i'); // fragment locator
  return pattern.test(str);
}

13
グーグル検索の画像リンクで失敗する:http://www.google.com/url?sa=i&rct=j&q=&esrc=s&source=images&cd=&docid=nIv5rk2GyP3hXM&tbnid=isiOkMe3nCtexM:&ved=0CAUQjRw&url=http%3A%2F%2Fanimalcrossing.wikia.com%2Fwiki%2FLion&ei=ygZXU_2fGKbMsQTf4YLgAQ&bvm=bv.65177938,d.aWc&psig=AFQjCNEpBfKnal9kU7Zu4n7RnEt2nerN4g&ust=1398298682009707
ビル・デイビス

7
これは使用できない遅いです
エルナンEche

3
@HernánEcheあなたが何を意味するので、遅いですかstart = new Date(); isURL("http://michalstefanow.com"); end = new Date(); diff = end - start; console.log(diff)私はやかんを置いて、母と呼ばれるトイレに行って、それはあっという間に完了しました...
Mars Robertson

62
それは返すtrueためにaaa
アレックスナウモフ2016

1
これは絶対に正しい答えではありません。多くのテストケースに失敗し、さらに重要なことに、短い文字列でもページがハングしますisURL('12345678901234567890123')。さらに文字を追加すると、さらに悪い結果になります。
aamarks 2018

141

あなたはURLコンストラクタを使うことを試みることができます:それがスローしない場合、文字列は有効なURLです:

function isValidUrl(string) {
  try {
    new URL(string);
  } catch (_) {
    return false;  
  }

  return true;
}

「URL」という用語はRFC 3886で(URIとして)定義されています。スキーム名で始まる必要があり、スキーム名はhttp / httpsに限定されません。

注目すべき例:

  • www.google.com は有効なURLではありません(スキームがありません)
  • javascript:void(0) 有効なURLですが、HTTPのURLではありません
  • http://..有効なURLで、ホスト..です。解決するかどうかはDNSに依存します
  • https://google..com 上記と同じ有効なURLです

文字列が有効なHTTP URLかどうかを確認する場合:

function isValidHttpUrl(string) {
  let url;

  try {
    url = new URL(string);
  } catch (_) {
    return false;  
  }

  return url.protocol === "http:" || url.protocol === "https:";
}

13
@AshDいいえ、そうではありません。たとえば、のhref属性として使用することはできません<a>。有効なURL は、スキーム名始まる必要がありますhttps://
Pavlo 2017

3
新しいURL( 'javascript:alert(23)')
blade091

6
@Pavloこれはtrueを返しますisValidUrl("javascript:void(0)")
Praveena

3
私はjsについて新しいことを私に教えるためにこれが好きです!私が見つけることができる偽陰性はありません。それはいくつかの誤http://..http:///a
検知を

2
URLはEdgeから機能しているため、それより下のすべては期待どおりに機能しない可能性があります。最初に互換性を確認してください。
トニーT.

97

正規表現を使用するのではなく、アンカー要素を使用することをお勧めします。

hrefプロパティを設定すると、anchor他のさまざまなプロパティが設定されます。

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

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

ソース

ただし、値hrefがバインドされている値が有効なURLではない場合、それらの補助プロパティの値は空の文字列になります。

編集:コメントで指摘されているように:無効なURLが使用された場合、現在のURLのプロパティが置き換えられる場合があります。

したがって、現在のページのURLを渡さない限り、次のようなことができます。

function isValidURL(str) {
   var a  = document.createElement('a');
   a.href = str;
   return (a.host && a.host != window.location.host);
}

3
これは事実ではありません(少なくともChrome 48では)。に渡されたURL a.hrefが無効な場合、parser.host期待されているではなく、現在アクセスしているページのホスト名を返しますfalse
サムベッカム

2
ガ!それは変だ。私はこれをテストしたと誓います!これは現在のページで実際に使用する必要はないので、条件を変更するだけでよいと言えます。投稿を編集します。
ルーク、

あまり一般的な使用例ではありませんが、この手法はFirefoxブラウザーウィンドウのコンテキストでは機能しません(アドオン開発にとって重要)
chrmod

@SamBeckhamこのメソッドを使用する場合、これは間違いなく問題ですが、これは特別な動作ではないことを指摘しておきます。などの無効なリンクがページにある場合<a href="invalidurl">、それドメインに移動します。現在のURLの末尾に追加されます。そのため、Chromeは「parser」要素から現在のホスト名を提供することで正しい処理を行っています。
yts

4
function isValidURL(str):正規表現を使用するよりもはるかに優れています!ありがとうございました!
ロドリゴ

46

以下の関数を使用して、URLの有無を検証しますhttp/https

function isValidURL(string) {
  var res = string.match(/(http(s)?:\/\/.)?(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/g);
  return (res !== null)
};

var testCase1 = "http://en.wikipedia.org/wiki/Procter_&_Gamble";
console.log(isValidURL(testCase1)); // return true

var testCase2 = "http://www.google.com/url?sa=i&rct=j&q=&esrc=s&source=images&cd=&docid=nIv5rk2GyP3hXM&tbnid=isiOkMe3nCtexM:&ved=0CAUQjRw&url=http%3A%2F%2Fanimalcrossing.wikia.com%2Fwiki%2FLion&ei=ygZXU_2fGKbMsQTf4YLgAQ&bvm=bv.65177938,d.aWc&psig=AFQjCNEpBfKnal9kU7Zu4n7RnEt2nerN4g&ust=1398298682009707";
console.log(isValidURL(testCase2)); // return true

var testCase3 = "https://sdfasd";
console.log(isValidURL(testCase3)); // return false

var testCase4 = "dfdsfdsfdfdsfsdfs";
console.log(isValidURL(testCase4)); // return false

var testCase5 = "magnet:?xt=urn:btih:123";
console.log(isValidURL(testCase5)); // return false

var testCase6 = "https://stackoverflow.com/";
console.log(isValidURL(testCase6)); // return true

var testCase7 = "https://w";
console.log(isValidURL(testCase7)); // return false

var testCase8 = "https://sdfasdp.ppppppppppp";
console.log(isValidURL(testCase8)); // return false


2
素晴らしい解決策のようです!いくつかのケースで機能することを示すテストを追加できますか(たとえば、これらのコメントを参照してください)?
Basj

@Basjはテストケースを追加しました。チェックしてください
Vikasdeep Singh 2018

悪くはありません。http://⌘.wsまたは142.42.1.1を渡せず、http://.www.foo.bar./を許可しますが、最高評価の回答を含む他の正規表現のようにハングしません。
aamarks 2018

@aamarks回答を確認しました。あなたの答えは、のために失敗しているhttps://sdfasdp.pppppppppppつまりは戻っtrueたが、鉱山リターンfalseが期待されると思います。
Vikasdeep Singh 2018

4
それが真実を返すのはsadf@gmail.com...すべきですか?私はそれはすべきでないと思います
Zohab Ali

35

JavaScriptを使用してURLを検証する方法を以下に示します

function ValidURL(str) {
  var regex = /(http|https):\/\/(\w+:{0,1}\w*)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%!\-\/]))?/;
  if(!regex .test(str)) {
    alert("Please enter valid URL.");
    return false;
  } else {
    return true;
  }
}

3
正規表現のいくつかの部分を大幅に削減することができます)(http|https)(?:https?)、b):{0,1}から:?; C)[0-9]\d
ドミトリーParzhitsky


23

受け入れられた回答の改善...

  • プロトコルとしてftp / ftpsを確認する
  • バックスラッシュ(\\)の二重エスケープ
  • ドメインにドットと拡張子(.com .io .xyz)があることを確認します
  • パスに完全なコロン(:)を許可します。例:http : //thingiverse.com/download : 1894343
  • パスにアンパサンド(&)を許可します。例:http : //en.wikipedia.org/wiki/Procter_&_Gamble
  • パスに@記号を使用できます。例:https : //medium.com/@techytimo

    isURL(str) {
      var pattern = new RegExp('^((ft|htt)ps?:\\/\\/)?'+ // protocol
      '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|'+ // domain name and extension
      '((\\d{1,3}\\.){3}\\d{1,3}))'+ // OR ip (v4) address
      '(\\:\\d+)?'+ // port
      '(\\/[-a-z\\d%@_.~+&:]*)*'+ // path
      '(\\?[;&a-z\\d%@_.,~+&:=-]*)?'+ // query string
      '(\\#[-a-z\\d_]*)?$','i'); // fragment locator
      return pattern.test(str);
    }

5
いいえ、それは受け入れられた答えであってはなりません。他のいくつかのように、それは単なる33文字の文字列:isURL( '123456789012345678901234567890123')でハングし、多くのエッジケーステストに失敗します:foo.com/blah_blah_(wikipedia)_( again) //誤ってfalseを返します。
aamarks 2018

2
これは、localhost:8080が有効なURLではないためです。
シェーン


ftps:// localhost:8080 =)にする必要があります
vp_arth

それは動作していないようです:(@aanmarksが言ったように)長い入力でハングします
cecemel

13

これはさらに別の方法です。

var elm;
function isValidURL(u){
  if(!elm){
    elm = document.createElement('input');
    elm.setAttribute('type', 'url');
  }
  elm.value = u;
  return elm.validity.valid;
}

console.log(isValidURL('http://www.google.com/'));
console.log(isValidURL('//google.com'));
console.log(isValidURL('google.com'));
console.log(isValidURL('localhost:8000'));


教育コード!ここでのメカニズムは、おそらくnew URL(string)Pavloのコードでの仕組みと同じです。どちらのテストでも、私がテストしたすべてのエッジケースで同じ結果が得られました。単純で要素の作成を含まないため、彼のコードが好きですが、あなたのコードは数倍高速です(おそらく、最初の使用後にelを作成しないためです)。
aamarks

1
ありがとうございました!私はあなたのアドバイスを実行しました。ただし、注意してください:古いブラウザーやモバイルデバイスのWebViewは、<input type = url>要素を実装していない場合があります。したがって、入力値は通常のテキストと同様に扱われます(URL検証なし)。REF:developer.mozilla.org/en-US/docs/Web/HTML/Element/input/url
Panini Luncher

10

ValidURLの例についてコメントする担当者がいないため、これを回答として投稿してください。)

プロトコル相対URLの使用は(奨励されていないもののプロトコル相対URL)、彼らは時々採用されますか。このようなURLを正規表現で検証するには、プロトコルの部分をオプションにすることができます。例:

function isValidURL(str) {
    var pattern = new RegExp('^((https?:)?\\/\\/)?'+ // protocol
        '(?:\\S+(?::\\S*)?@)?' + // authentication
        '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|'+ // domain name
        '((\\d{1,3}\\.){3}\\d{1,3}))'+ // OR ip (v4) address
        '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*'+ // port and path
        '(\\?[;&a-z\\d%_.~+=-]*)?'+ // query string
        '(\\#[-a-z\\d_]*)?$','i'); // fragment locater
    if (!pattern.test(str)) {
        return false;
    } else {
        return true;
    }
}

ただし、他の人が指摘したように、正規表現はURLの検証に最適な方法ではないようです。


私は最初これはかなり良いと思いましたが、mathiasbynens.be/demo/urlisValidURL("https://d1f4470da51b49289906b3d6cbd65074@app.getsentry.com/13176")
regex

はい、私が言ったように、私は単にプロトコル部分についてコメントしました。処理する認証句を追加しました@。私のブラウザーではハングしません。
ko la

申し訳ありませんが、これらを評価するためにこれらのいくつかを調べていましたが、あなたの答えが与えられた答えにコメントしていたことを逃しました。私がこのページに初めてアクセスしたとき、あなたの訂正は私がこれらを始めるのを助けたとさえ思います。今ぶら下がっていません。
aamarks 2018

9

URLネイティブAPIを使用できます

  const isUrl = string => {
      try { return Boolean(new URL(string)); }
      catch(e){ return false; }
  }

3
@pavloによって提供された回答と非常によく似ていますが、変数名のみが変更されました;)
Munim Munna

2
これまでにこれをチェックする単純なネイティブメソッドがあるはずです。この答えは非常に有望に見えましたが、@ Basjが前述したように、早い段階でtrueを返します。
zero_cool 2018

8

すでに述べたように、完全な正規表現はとらえどころのないものですが、それでも妥当なアプローチのようです(代替案はサーバー側のテストまたは新しい実験的なURL APIです)。ただし、上位の回答は一般的なURLに対してfalseを返すことがよくありますが、さらに悪いことに、のような単純な文字列であっても、アプリ/ページが数分間フリーズしますisURL('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')。一部のコメントで指摘されていますが、おそらくそれを確認するために悪い値を入力していません。そのようにぶら下がると、そのコードは深刻なアプリケーションでは使用できなくなります。これは、のようなコードで大文字と小文字を区別しないセットが繰り返されているためだと思います((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.?)+[a-z]{2,}|' ...。「i」を外すとハングしませんが、もちろん期待どおりに動作しません。ただし、大文字と小文字を区別しないフラグがあっても、これらのテストは許可されている高いUnicode値を拒否します。

すでに述べた最高のものは:

function isURL(str) {
  return /^(?:\w+:)?\/\/([^\s\.]+\.\S{2}|localhost[\:?\d]*)\S*$/.test(str); 
}

それはGithub segmentio / is-urlから来ています。コードリポジトリの良い点は、テストと問題を確認でき、テスト文字列が実行されることです。のようgoogle.comにプロトコルが欠けている文字列を許可するブランチがありますが、おそらくあまりにも多くの仮定をしているでしょう。リポジトリが更新されたので、ここでミラーを維持するつもりはありません。DOS攻撃に悪用される可能性のあるRegEx redosを回避するために、個別のテストに分割されています(クライアント側のjsでそれを心配する必要はないと思いますが、ページが長時間ハングすることを心配する必要があります)訪問者があなたのサイトを離れます)。

他にも、dperini / regex-weburl.jsのisURLに適していると思われるリポジトリが1つありますが、非常に複雑です。有効なURLと無効なURLの大きなテストリストがあります。上記の単純なものは、すべてのポジティブを通過http://a.b--c.de/し、特別なIPと同様に、いくつかの奇数のネガティブをブロックすることに失敗します。

どちらを選択しても、ブラウザーの開発者ツールインペクターを使用しながら、dperini / regex-weburl.jsのテストから適応させたこの関数を使用して実行します。

function testIsURL() {
//should match
console.assert(isURL("http://foo.com/blah_blah"));
console.assert(isURL("http://foo.com/blah_blah/"));
console.assert(isURL("http://foo.com/blah_blah_(wikipedia)"));
console.assert(isURL("http://foo.com/blah_blah_(wikipedia)_(again)"));
console.assert(isURL("http://www.example.com/wpstyle/?p=364"));
console.assert(isURL("https://www.example.com/foo/?bar=baz&inga=42&quux"));
console.assert(isURL("http://✪df.ws/123"));
console.assert(isURL("http://userid:password@example.com:8080"));
console.assert(isURL("http://userid:password@example.com:8080/"));
console.assert(isURL("http://userid@example.com"));
console.assert(isURL("http://userid@example.com/"));
console.assert(isURL("http://userid@example.com:8080"));
console.assert(isURL("http://userid@example.com:8080/"));
console.assert(isURL("http://userid:password@example.com"));
console.assert(isURL("http://userid:password@example.com/"));
console.assert(isURL("http://142.42.1.1/"));
console.assert(isURL("http://142.42.1.1:8080/"));
console.assert(isURL("http://➡.ws/䨹"));
console.assert(isURL("http://⌘.ws"));
console.assert(isURL("http://⌘.ws/"));
console.assert(isURL("http://foo.com/blah_(wikipedia)#cite-1"));
console.assert(isURL("http://foo.com/blah_(wikipedia)_blah#cite-1"));
console.assert(isURL("http://foo.com/unicode_(✪)_in_parens"));
console.assert(isURL("http://foo.com/(something)?after=parens"));
console.assert(isURL("http://☺.damowmow.com/"));
console.assert(isURL("http://code.google.com/events/#&product=browser"));
console.assert(isURL("http://j.mp"));
console.assert(isURL("ftp://foo.bar/baz"));
console.assert(isURL("http://foo.bar/?q=Test%20URL-encoded%20stuff"));
console.assert(isURL("http://مثال.إختبار"));
console.assert(isURL("http://例子.测试"));
console.assert(isURL("http://उदाहरण.परीक्षा"));
console.assert(isURL("http://-.~_!$&'()*+,;=:%40:80%2f::::::@example.com"));
console.assert(isURL("http://1337.net"));
console.assert(isURL("http://a.b-c.de"));
console.assert(isURL("http://223.255.255.254"));
console.assert(isURL("postgres://u:p@example.com:5702/db"));
console.assert(isURL("https://d1f4470da51b49289906b3d6cbd65074@app.getsentry.com/13176"));

//SHOULD NOT MATCH:
console.assert(!isURL("http://"));
console.assert(!isURL("http://."));
console.assert(!isURL("http://.."));
console.assert(!isURL("http://../"));
console.assert(!isURL("http://?"));
console.assert(!isURL("http://??"));
console.assert(!isURL("http://??/"));
console.assert(!isURL("http://#"));
console.assert(!isURL("http://##"));
console.assert(!isURL("http://##/"));
console.assert(!isURL("http://foo.bar?q=Spaces should be encoded"));
console.assert(!isURL("//"));
console.assert(!isURL("//a"));
console.assert(!isURL("///a"));
console.assert(!isURL("///"));
console.assert(!isURL("http:///a"));
console.assert(!isURL("foo.com"));
console.assert(!isURL("rdar://1234"));
console.assert(!isURL("h://test"));
console.assert(!isURL("http:// shouldfail.com"));
console.assert(!isURL(":// should fail"));
console.assert(!isURL("http://foo.bar/foo(bar)baz quux"));
console.assert(!isURL("ftps://foo.bar/"));
console.assert(!isURL("http://-error-.invalid/"));
console.assert(!isURL("http://a.b--c.de/"));
console.assert(!isURL("http://-a.b.co"));
console.assert(!isURL("http://a.b-.co"));
console.assert(!isURL("http://0.0.0.0"));
console.assert(!isURL("http://10.1.1.0"));
console.assert(!isURL("http://10.1.1.255"));
console.assert(!isURL("http://224.1.1.1"));
console.assert(!isURL("http://1.1.1.1.1"));
console.assert(!isURL("http://123.123.123"));
console.assert(!isURL("http://3628126748"));
console.assert(!isURL("http://.www.foo.bar/"));
console.assert(!isURL("http://www.foo.bar./"));
console.assert(!isURL("http://.www.foo.bar./"));
console.assert(!isURL("http://10.1.1.1"));}

そして、その「a」の文字列をテストします。

一見すばらしい正規表現を投稿する前に、詳細については、Mathias BynensによるisURL正規表現の比較をご覧ください。


答えを確認しました。あなたの答えはsdfasdp.pppppppppppに対して失敗しています。つまり、trueを返しますが、期待はfalseです
Vikasdeep Singh

1
構造的には有効なURLだと思います。標準の専門家ではありませんが、.com部分の長さに制限はないと思います(.onlineは合法です)。
aamarks 2018

1
数ヶ月前に正規表現を書く方法をほとんど知りませんでした。問題は深刻です。私が引用した正規表現はどちらもisURL('a'.repeat(100))数百万回/秒を完了することができます(dperiniからのより複雑な方が実際には高速です)。([a-zA-Z] +)*という形式の上位の回答の一部は、一度完了するまでに数時間かかる場合があります。詳細については、RegEx redosを検索してください。
aamarks

6

#5717133に最も近い投稿にはコメントできませんが、@ tom-gullen regexを機能させる方法を以下に示します。

/^(https?:\/\/)?((([a-z\d]([a-z\d-]*[a-z\d])*)\.)+[a-z]{2,}|((\d{1,3}\.){3}\d{1,3}))(\:\d+)?(\/[-a-z\d%_.~+]*)*(\?[;&a-z\d%_.~+=-]*)?(\#[-a-z\d_]*)?$/i

2
これでうまくいきましたが、バックスラッシュをバックスラッシュする必要がありました。var pattern = new RegExp('(https?:\\/\\/)?((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|((\\d{1,3}\\.){3}\\d{1,3}))(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*(\\?[;&a-z\\d%_.~+=-]*)?(\\#[-a-z\\d_]*)?$', 'i');
フェルナンドチャベスエレーラ

その他のテストケースについては、w3resource.com / javascript
exercises

5

validator.jsを使用する

ES6

import isURL from 'validator/lib/isURL'

isURL(string)

ES6なし

var validator = require('validator');

validator.isURL(string)

オプションのoptionsオブジェクトを2番目の引数として渡すことにより、この関数の動作を微調整することもできます。isURL

デフォルトのoptionsオブジェクトは次のとおりです。

let options = {
    protocols: [
        'http',
        'https',
        'ftp'
    ],
    require_tld: true,
    require_protocol: false,
    require_host: true,
    require_valid_protocol: true,
    allow_underscores: false,
    host_whitelist: false,
    host_blacklist: false,
    allow_trailing_dot: false,
    allow_protocol_relative_urls: false,
    disallow_auth: false
}

isURL(string, options)

host_whitelistそしてhost_blacklistホストのアレイとすることができます。また、正規表現もサポートしています。

let options = {
    host_blacklist: ['foo.com', 'bar.com'],
}

isURL('http://foobar.com', options) // => true
isURL('http://foo.bar.com/', options) // => true
isURL('http://qux.com', options) // => true

isURL('http://bar.com/', options) // => false
isURL('http://foo.com/', options) // => false


options = {
    host_blacklist: ['bar.com', 'foo.com', /\.foo\.com$/],
}

isURL('http://foobar.com', options) // => true
isURL('http://foo.bar.com/', options) // => true
isURL('http://qux.com', options) // => true

isURL('http://bar.com/', options) // => false
isURL('http://foo.com/', options) // => false
isURL('http://images.foo.com/', options) // => false
isURL('http://cdn.foo.com/', options) // => false
isURL('http://a.b.c.foo.com/', options) // => false

1
いいね!小さなライブラリ(4万円未満に縮小)、人気のあるライブラリ(npmで毎週3Mを超えるダウンロード)は、特定のユースケースのURLの有効性を柔軟に指定でき、URL以外にも多数のバリデーターを備えています。これは断然最良の答えです。
Javid Jamae

4

URL「文字列」の検証に使用している関数の1つは次のとおりです。

var matcher = /^(?:\w+:)?\/\/([^\s\.]+\.\S{2}|localhost[\:?\d]*)\S*$/;

function isUrl(string){
  return matcher.test(string);
}

この関数は、文字列がURLかどうかに関係なくブール値を返します。

例:

isUrl("https://google.com");     // true
isUrl("http://google.com");      // true
isUrl("http://google.de");       // true
isUrl("//google.de");            // true
isUrl("google.de");              // false
isUrl("http://google.com");      // true
isUrl("http://localhost");       // true
isUrl("https://sdfasd");         // false

4

URLには多くの「不都合」があるため、これを純粋な正規表現で行うのは非常に困難です。

  1. たとえば、ドメイン名にはハイフンに対する複雑な制限があります。

    a。途中に多くの連続したハイフンを含めることができます。

    b。ただし、ドメイン名の最初と最後の文字をハイフンにすることはできません

    c。3番目と4番目の文字を両方ハイフンにすることはできません

  2. 同様に、ポート番号は1〜65535の範囲でのみ指定できます。これは、ポート部分を抽出して変換すると簡単に確認できますintが、正規表現で確認するのは非常に困難です。

  3. また、有効なドメイン拡張子を確認する簡単な方法もありません。一部の国にはセカンドレベルドメイン(「co.uk」など)があるか、拡張子が「.international」のように長い単語になることがあります。また、新しいTLDが定期的に追加されます。このタイプのものは、ハードコーディングされたリストに対してのみチェックできます。(https://en.wikipedia.org/wiki/Top-level_domainを参照)

  4. 次に、マグネットURL、FTPアドレスなどがあります。これらはすべて異なる要件を持っています。

それでも、以下はほとんどすべてを処理する関数です。

  • ケース1. c
  • 1から5桁のポート番号を受け入れます
  • 2〜13文字の拡張子を受け入れます
  • FTP、マグネットなどを受け入れません...

function isValidURL(input) {
    pattern = '^(https?:\\/\\/)?' + // protocol
        '((([a-zA-Z\\d]([a-zA-Z\\d-]{0,61}[a-zA-Z\\d])*\\.)+' + // sub-domain + domain name
        '[a-zA-Z]{2,13})' + // extension
        '|((\\d{1,3}\\.){3}\\d{1,3})' + // OR ip (v4) address
        '|localhost)' + // OR localhost
        '(\\:\\d{1,5})?' + // port
        '(\\/[a-zA-Z\\&\\d%_.~+-:@]*)*' + // path
        '(\\?[a-zA-Z\\&\\d%_.,~+-:@=;&]*)?' + // query string
        '(\\#[-a-zA-Z&\\d_]*)?$'; // fragment locator
    regex = new RegExp(pattern);
    return regex.test(input);
}

let tests = [];
tests.push(['', false]);
tests.push(['http://en.wikipedia.org/wiki/Procter_&_Gamble', true]);
tests.push(['https://sdfasd', false]);
tests.push(['http://www.google.com/url?sa=i&rct=j&q=&esrc=s&source=images&cd=&docid=nIv5rk2GyP3hXM&tbnid=isiOkMe3nCtexM:&ved=0CAUQjRw&url=http%3A%2F%2Fanimalcrossing.wikia.com%2Fwiki%2FLion&ei=ygZXU_2fGKbMsQTf4YLgAQ&bvm=bv.65177938,d.aWc&psig=AFQjCNEpBfKnal9kU7Zu4n7RnEt2nerN4g&ust=1398298682009707', true]);
tests.push(['https://stackoverflow.com/', true]);
tests.push(['https://w', false]);
tests.push(['aaa', false]);
tests.push(['aaaa', false]);
tests.push(['oh.my', true]);
tests.push(['dfdsfdsfdfdsfsdfs', false]);
tests.push(['google.co.uk', true]);
tests.push(['test-domain.MUSEUM', true]);
tests.push(['-hyphen-start.gov.tr', false]);
tests.push(['hyphen-end-.com', false]);
tests.push(['https://sdfasdp.international', true]);
tests.push(['https://sdfasdp.pppppppp', false]);
tests.push(['https://sdfasdp.ppppppppppppppppppp', false]);
tests.push(['https://sdfasd', false]);
tests.push(['https://sub1.1234.sub3.sub4.sub5.co.uk/?', true]);
tests.push(['http://www.google-com.123', false]);
tests.push(['http://my--testdomain.com', false]);
tests.push(['http://my2nd--testdomain.com', true]);
tests.push(['http://thingiverse.com/download:1894343', true]);
tests.push(['https://medium.com/@techytimo', true]);
tests.push(['http://localhost', true]);
tests.push(['localhost', true]);
tests.push(['localhost:8080', true]);
tests.push(['localhost:65536', true]);
tests.push(['localhost:80000', false]);
tests.push(['magnet:?xt=urn:btih:123', true]);

for (let i = 0; i < tests.length; i++) {
    console.log('Test #' + i + (isValidURL(tests[i][0]) == tests[i][1] ? ' passed' : ' failed') + ' on ["' + tests[i][0] + '", ' + tests[i][1] + ']');
}


1

@pavloが示唆するように、ネイティブURL APIを使用する方が複雑な正規表現パターンよりも優れていると思います。それにはいくつかの欠点がありますが、いくつかの追加コードで修正できます。このアプローチは、次の有効なURLでは失敗します。

//cdn.google.com/script.js

これを回避するために、不足しているプロトコルを事前に追加できます。また、次の無効なURLの検出にも失敗します。

http://w
http://..

では、なぜURL全体を確認するのでしょうか。ドメインを確認するだけです。ここからドメインを確認するために正規表現を借りました。

function isValidUrl(string) {
    if (string && string.length > 1 && string.slice(0, 2) == '//') {
        string = 'http:' + string; //dummy protocol so that URL works
    }
    try {
        var url = new URL(string);
        return url.hostname && url.hostname.match(/^([a-z0-9])(([a-z0-9-]{1,61})?[a-z0-9]{1})?(\.[a-z0-9](([a-z0-9-]{1,61})?[a-z0-9]{1})?)?(\.[a-zA-Z]{2,4})+$/) ? true : false;
    } catch (_) {
        return false;
    }
}

hostname属性はの空の文字列なjavascript:void(0)ので、それでも機能し、IPアドレス検証も追加できます。私はネイティブAPIに最も固執したいと思います。近い将来、すべてがサポートされるようになることを願っています。


興味深いですが、正規表現に取り組む必要があるかもしれnew URLません。これは、私が行ったテストにはない偽陰性が導入されているためです。これは:http://142.42.1.1 //falseを呼び出しており、高いUnicode文字列をブロックしています。
aamarks

1

この質問ではstackoverflow、ホスト名にプロトコルやドットを使用せずに、などのURLの検証方法を尋ねます。つまり、URL構文を検証することではなく、実際に呼び出して、URLが有効かどうかを確認することです。

URLがtrueであり、ブラウザー内から呼び出し可能かどうかを確認するためにいくつかの方法を試しましたが、呼び出しの応答ヘッダーをJavaScriptでテストする方法が見つかりませんでした。

  • click()メソッドを起動するには、アンカー要素を追加するのが適切です。
  • で挑戦的なURLにajax呼び出しを行うことは問題ありませんが、ポリシー'GET'によりさまざまな制限CORSがあり、を使用する場合とajaxは異なります。URLがサーバーのドメイン外の可能性があるためです。
  • フェッチAPIを使用すると、ajaxと同様の回避策があります
  • その他の問題は、httpsプロトコルにサーバーがあり、非セキュアなURLを呼び出すと例外がスローされることです。

したがって、私が考えることができる最良の解決策は、のCURLようなものを試すJavaScript を使用して実行するためのツールを入手することですcurl -I <url>。残念ながら私は何も見つけられなかったし、見たところそれは不可能です。これについてのコメントをいただければ幸いです。

しかし、最終的にはサーバーを実行していて、PHPほとんどすべての要求にAjaxを使用しているため、サーバー側でcurl要求を実行してブラウザーに戻る関数を作成しました。

「stackoverflow」という質問の単一の単語のurlについてはhttps://daniserver.com.ar/stackoverflow、daniserver.com.arが私の独自ドメインである


OPはおそらく彼の意図をより多く示しているはずです。問題は確かに、ニーズと、誤検知を除外するか、誤検知を含めることが重要かによって異なります。問題が述べられているので、私には答えがないようです。あなたは本当にfooそれをhttpまたはhttpsまたは.comまたは.esまたは無数のサフィックスのいずれかであると想定できますか?あなたは本当になるまで台所の流しをそれに投げ続けますか?
aamarks

1

これはCSで最も難しい問題の1つであるようです;)

これは、私にとって十分に機能し、ここで見た他のソリューションよりも優れている、もう1つの不完全なソリューションです。IE11をサポートするためにinput [type = url]を使用していますが、そうでない場合は、代わりにwindow.URLを使用して検証を実行する方がはるかに簡単です。

const ipv4Regex = /^(\d{1,3}\.){3}\d{1,3}$/;
function isValidIpv4(ip) {
  if (!ipv4Regex.test(ip)) return false;
  return !ip.split('.').find(n => n > 255);
}

const domainRegex = /(?:[a-z0-9-]{1,63}\.){1,125}[a-z]{2,63}$/i;
function isValidDomain(domain) {
  return isValidIpv4(domain) || domainRegex.test(domain);
}

let input;
function validateUrl(url) {
  if (! /^https?:\/\//.test(url)) url = `http://${url}`; // assuming Babel is used
  // to support IE11 we'll resort to input[type=url] instead of window.URL:
  // try { return isValidDomain(new URL(url).host) && url; } catch(e) { return false; }
  if (!input) { input = document.createElement('input'); input.type = 'url'; }
  input.value = url;
  if (! input.validity.valid) return false;
  const domain = url.split(/^https?:\/\//)[1].split('/')[0].split('@').pop();
  return isValidDomain(domain) && url;
}

console.log(validateUrl('google'), // false
  validateUrl('user:pw@mydomain.com'),
  validateUrl('https://google.com'),
  validateUrl('100.100.100.100/abc'),
  validateUrl('100.100.100.256/abc')); // false

「www.mydomain.com」などの不完全な入力を受け入れるために、プロトコルが「http」であると想定して有効にし、アドレスが有効な場合は有効なURLを返します。無効な場合はfalseを返します。

IPv4ドメインもサポートしますが、IPv6はサポートしません。


1

私の場合、私の唯一の要件は、ユーザー入力がタグのhrefに配置されたときに相対リンクとして解釈されず、ここでの回答がそのための少しOTTまたは許可されたURLが私の要件を満たしていないことです。私がやっていることです:

^https?://.+$

同じことは正規表現なしでかなり簡単に達成できました。


1

これは私と一緒に働いています

function isURL(str) {
  var regex = /(http|https):\/\/(\w+:{0,1}\w*)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%!\-\/]))?/;
  var pattern = new RegExp(regex); 
return pattern.test(str);
}

1
この回答は、4年以上前にkavitha Reddyによって既に提供されています。
aamarks

私はそれをよりシンプルで抽象的なものにしました
HeshamSalama

1

入力タイプを変更できる場合、この解決策ははるかに簡単になると思います。

type="url"入力で簡単に使用できcheckValidity()、jsでチェックできます

例えば:

your.html

<input id="foo" type="url">

your.js

// The selector is JQuery, but the function is plain JS
$("#foo").on("keyup", function() {
    if (this.checkValidity()) {
        // The url is valid
    } else {
        // The url is invalid
    }
});

1

これは間違いなく最も効果的なアプローチではありませんが、読みやすく、必要なものに簡単に形成できます。そして、ここから正規表現/複雑さを追加する方が簡単です。だからここは非常に実用的なアプローチです

const validFirstBits = ["ftp://", "http://", "https://", "www."];
const invalidPatterns = [" ", "//.", ".."];

export function isUrl(word) {
// less than www.1.dk
if (!word || word.length < 8) return false;

// Let's check and see, if our candidate starts with some of our valid first bits
const firstBitIsValid = validFirstBits.some(bit => word.indexOf(bit) === 0);
if (!firstBitIsValid) return false;

const hasInvalidPatterns = invalidPatterns.some(
    pattern => word.indexOf(pattern) !== -1,
);

if (hasInvalidPatterns) return false;

const dotSplit = word.split(".");
if (dotSplit.length > 1) {
    const lastBit = dotSplit.pop(); // string or undefined
    if (!lastBit) return false;
    const length = lastBit.length;
    const lastBitIsValid =
        length > 1 || (length === 1 && !isNaN(parseInt(lastBit)));
    return !!lastBitIsValid;
}

    return false;
}

テスト:

import { isUrl } from "./foo";

describe("Foo", () => {
    test("should validate correct urls correctly", function() {
        const validUrls = [
            "http://example.com",
            "http://example.com/blah",
            "http://127.0.0.1",
            "http://127.0.0.1/wow",
            "https://example.com",
            "https://example.com/blah",
            "https://127.0.0.1:1234",
            "ftp://example.com",
            "ftp://example.com/blah",
            "ftp://127.0.0.1",
            "www.example.com",
            "www.example.com/blah",
        ];

        validUrls.forEach(url => {
            expect(isUrl(url) && url).toEqual(url);
        });
    });

    test("should validate invalid urls correctly", function() {
        const inValidUrls = [
            "http:// foo.com",
            "http:/foo.com",
            "http://.foo.com",
            "http://foo..com",
            "http://.com",
            "http://foo",
            "http://foo.c",
        ];

        inValidUrls.forEach(url => {
            expect(!isUrl(url) && url).toEqual(url);
        });
    });
});

1

Mathias Bynensは、よく知られているURL正規表現とテストURLのリストをまとめました。新しい正規表現を書く理由はほとんどありません。自分に最適な既存のものを選択してください。

しかし、それらの正規表現の比較表は、単一の正規表現でURL検証を行うことがほぼ不可能であることも示しています。Bynensのリストのすべての正規表現は、偽陽性と偽陰性を生成します。

既存のURLパーサー(new URL('http://www.example.com/')JavaScriptなど)を使用して、解析した正規化された形式のURL応答に対して実行するチェックを適用することをお勧めします。そのコンポーネント。JavaScript URLインターフェースを使用すると、ブラウザーによって実際に受け入れられるURLのみを受け入れるという追加の利点があります。

また、技術的に正しくないURLでも機能する可能性があることに注意してください。たとえばhttp://w_w_w.example.com/http://www..example.com/http://123.example.com/すべてが無効なホスト名部分を持っていますが、私が知っているすべてのブラウザは、苦情なしでそれらを開こうとします、そしてあなたはそれらの無効な名前のためのIPアドレスを指定するとき/etc/hosts/、このようなURLにしても動作しますが、唯一のコンピュータ上します。

したがって、問題は、URLが有効であるかどうかではなく、特定のコンテキストでどのURLが機能し、許可されるかです。

URL検証を実行したい場合、見落としがちな詳細情報やエッジケースがたくさんあります。

  • のように、URLには認証情報が含まれる場合がありますhttp://user:password@www.example.com/
  • ポート番号は0〜65535の範囲でなければなりませんが、ワイルドカードポート0を除外することもできます。
  • ポート番号には、http://www.example.com: 000080/のように先行ゼロが含まれる場合があります
  • IPv4アドレスは、0〜255の範囲の4つの10進整数に決して制限されません。1〜4つの整数を使用でき、10進数、8進数、または16進数を使用できます。URLをHTTPS://010.010.000010.010/HTTPS://0x8.0x8.0x0008.0x8/HTTPS://8.8.2056/HTTPS://8.526344/https://で134744072 /すべて有効であり、https://8.8.8.8/を作成するための創造的な方法。
  • ループバックアドレス(http://127.0.0.1/)、プライベートIPアドレス(http://192.168.1.1)、リンクローカルアドレス(http://169.254.100.200)などを許可すると、セキュリティまたはプライバシー。たとえば、それらをフォーラムのユーザーアバターのアドレスとして許可した場合、ユーザーのブラウザがローカルネットワークおよびインターネットで未承諾のネットワークリクエストを送信するようにして、そのようなリクエストが面白いことを引き起こし、それほど面白いことではないことがあります。あなたの家で起こります。
  • 同じ理由で、完全修飾されていないホスト名、つまりドットのないホスト名へのリンクを破棄したい場合があります。
  • ただし、ホスト名には常に(のようにhttp://www.stackoverflow.com.)ドットが続く場合があります。
  • リンクのホスト名部分には、http:// [:: 1]のようにIPv6アドレスの山括弧が含まれる場合があります。
  • IPv6アドレスには、プライベートネットワークやリンクローカルアドレスなどの範囲もあります。
  • 特定のIPv4アドレスをブロックする場合、たとえば、https://127.0.0.1https:// [:: ffff:127.0.0.1]が同じリソースを指していることに注意してください(マシンのループバックデバイスがIPv6対応の場合) )。
  • URLのホスト名部分にUnicodeが含まれる可能性があるため、文字範囲だけで[-0-9a-zA-z]は十分ではなくなります。
  • トップレベルドメインの多くのレジストリでは、許可されたUnicode文字セットなど、特定の制限が定義されています。または、名前空間を細分します(co.ukなど)。
  • トップレベルドメインに10進数を含めることはできません。また、IDN Aラベルプレフィックス "xn--"を除いて、ハイフンは使用できません。
  • Unicodeトップレベルドメイン(および "xn--"を使用したpunycodeエンコーディング)には文字のみを含める必要がありますが、正規表現でそれを確認したいのは誰ですか?

これらの制限とルールのどれが適用されるかは、プロジェクトの要件と好みの問題です。

最近、フォーラムやソーシャルネットワークなどでユーザーが指定したURLに適したWebアプリのURLバリデーターを作成しました。自分のベースとして自由に使ってください:

また、より詳細な情報を記載したURL検証の詳細をブログに書いています。


1

私は関数をMatch +に変更し、ここでスラッシュとその作業を変更します:(http://とhttps)両方

function isValidUrl(userInput) {
    var res = userInput.match(/(http(s)?:\/\/.)?(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/g);
    if(res == null)
       return false;
    else
       return true;
}

0

以下は、有効なプロトコルが存在することを確認するための非常に単純なチェックです。ドメイン拡張子は2文字以上である必要があります。

is_valid_url = ( $url ) => {

    let $url_object = null;

    try {
        $url_object = new URL( $url );
    } catch ( $error ) {
        return false;
    }

    const $protocol = $url_object.protocol;
    const $protocol_position = $url.lastIndexOf( $protocol );
    const $domain_extension_position = $url.lastIndexOf( '.' );

    return (
        $protocol_position === 0 &&
        [ 'http:', 'https:' ].indexOf( $protocol ) !== - 1 &&
        $domain_extension_position > 2 && $url.length - $domain_extension_position > 2
    );

};

0

サポートする必要がある場合はhttps://localhost:3000、この変更されたバージョンの[Devshed]の正規表現を使用します。

    function isURL(url) {
        if(!url) return false;
        var pattern = new RegExp('^(https?:\\/\\/)?'+ // protocol
            '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|'+ // domain name
            '((\\d{1,3}\\.){3}\\d{1,3}))|' + // OR ip (v4) address
            'localhost' + // OR localhost
            '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*'+ // port and path
            '(\\?[;&a-z\\d%_.~+=-]*)?'+ // query string
            '(\\#[-a-z\\d_]*)?$', 'i'); // fragment locator
        return pattern.test(url);
    }

0

URLコンストラクターを使用するいくつかのテストがあります。これらのテストは、入力が文字列オブジェクトであるかURLオブジェクトであるかを区別しません。

// Testing whether something is a URL
function isURL(url) {
    return toString.call(url) === "[object URL]";
}

// Testing whether the input is both a string and valid url:
function isUrl(url) {
    try {
        return toString.call(url) === "[object String]" && !!(new URL(url));
    } catch (_) {
        return false;  
    }
}

0

2020年の更新。@iamnewtonと@Fernando Chavez Herreraからの優れた回答の両方を拡張するために@、URLのパスで使用されているのを見始めました。

したがって、更新された正規表現は次のとおりです。

RegExp('(https?:\\/\\/)?((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|((\\d{1,3}\\.){3}\\d{1,3}))(\\:\\d+)?(\\/[-a-z\\d%_.~+@]*)*(\\?[;&a-z\\d%_.~+=-]*)?(\\#[-a-z\\d_]*)?$', 'i');

クエリ文字列とハッシュで許可する場合は、次を使用します。

RegExp('(https?:\\/\\/)?((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|((\\d{1,3}\\.){3}\\d{1,3}))(\\:\\d+)?(\\/[-a-z\\d%_.~+@]*)*(\\?[;&a-z\\d%_.~+=-@]*)?(\\#[-a-z\\d_@]*)?$', 'i');

そうは言っても@、クエリ文字列またはハッシュで許可されていないホワイトペーパールールがあるかどうかはわかりません。


0

すでに多くの回答がありますが、ここに別の貢献があります:URLポリフィルの有効性チェックから直接取得し、ブラウザーの組み込みの有効性チェックを利用するためにinput要素を使用しますtype="url"

var inputElement = doc.createElement('input');
inputElement.type = 'url';
inputElement.value = url;

if (!inputElement.checkValidity()) {
    throw new TypeError('Invalid URL');
}

ソース

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