Проверьте, является ли строка JavaScript URL

284

Есть ли в JavaScript способ проверить, является ли строка URL-адресом?

RegExes исключены, потому что URL, скорее всего, написан как stackoverflow; то есть сказать , что она не может иметь .com, wwwили http.

Bruno
источник
22
Если он отсутствует http, по умолчанию это не URL.
nfechner
1
@nfechner, то есть если он не указывает протокол и не использует символ двоеточия (желательно с двумя косыми чертами далее), то это не URL?
Jcolebrand
5
Как вы можете прочитать в URL RFC , единственной частью, которая действительно необходима для того, чтобы сделать String действительным URL-адресом, является двоеточие. Действительные URL выглядят так:<scheme>:<scheme-specific-part>
nfechner,
8
То, как вы проверяете, является ли что-то URL, сильно зависит от контекста и слишком расплывчато без дальнейшей квалификации Имеет ли значение для вас, соответствует ли он спецификации RFC URL, работает, когда системный вызов ОС открывает URL , анализируется как hrefэлемент привязки, работает при вызове window.open(url), указывает на то, что действительно существует, работает в расположении браузера бар или комбинация вышеперечисленного? Вы получите очень разные ответы в зависимости от того, какой из них вам небезразличен.
Рой Тинкер

Ответы:

189

Смежный вопрос с ответом:

Соответствие URL регулярного выражения Javascript

Или это регулярное выражение из 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 и т. Д.)
Бруно
4
@Bruno: весьма вероятно, что они сохраняются внутри с отдельными заголовками и URL-адресами, например, « { title: "Stackoverflow", uri: "http://stackoverflow.com" } Обновление»: действительно, см. Code.google.com/chrome/extensions/bookmarks.html
Марсель Корпел
10
пытаясь использовать ваш пример. Но я получаю ошибку на firebug, которая говорит invalid quantifier. Любая идея?
Сисир
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
10
Имейте в виду, что если вы используете строку в качестве параметра для RegExpвас, вы должны дважды избежать обратной косой черты - в противном случае вы получите ошибки, такие как недопустимая группа .
Кьелл
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);
}
Zemljoradnik
источник
13
не удается найти ссылки для поиска в Google: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
это непригодный медленный
Эрнан Эче
3
@ HernánEche Что ты имеешь в виду под медленным ? start = new Date(); isURL("http://michalstefanow.com"); end = new Date(); diff = end - start; console.log(diff)Я поставил чайник, пошел в туалет, позвонил моей маме, и все было сделано в кратчайшие сроки ...
Марс Робертсон
62
Это возвращается trueдля aaa.
Алекс Наумов
1
Это абсолютно не должно быть правильным ответом. Он не проходит много тестов и, что более важно, он вешает вашу страницу даже на короткую строку: isURL('12345678901234567890123')добавьте еще несколько символов, и это еще хуже.
aamarks
142

Вы можете попробовать использовать 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
  • 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://.
Павло
3
новый URL ('javascript: alert (23)')
blade091
6
@Pavlo это возвращает правдаisValidUrl("javascript:void(0)")
Правина
3
Мне нравится это для того, чтобы учить меня новым вещам о JS! У него нет ложных негативов, которые я мог бы найти. У него есть несколько ложных срабатываний: http://..илиhttp:///a
aamarks
2
URL работает начиная с Edge, поэтому все, что находится ниже, может работать не так, как вы ожидаете. Убедитесь, что вы проверите совместимость в первую очередь.
Тони Т.
97

Вместо того, чтобы использовать регулярное выражение, я бы рекомендовал использовать элемент привязки.

когда вы устанавливаете hrefсвойство an 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 (важно для разработки
аддонов
@ SamBeckham Это определенно проблема при использовании этого метода, но я просто хочу отметить, что это не особенное поведение. Если у вас есть ссылка на вашей странице , которая является недействительной, как <a href="invalidurl">она делает идти к вашему домену. Он добавляется в конец текущего URL. Таким образом, Chrome делает правильную вещь, предоставляя вам текущее имя хоста из элемента "parser".
YTS
4
function isValidURL(str): гораздо лучше, чем с помощью регулярных выражений! Спасибо!
Родриго
47

Я использую функцию ниже для проверки 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 добавил тестовые случаи. Пожалуйста, проверьте
Vikasdeep Singh
Неплохо, не может передать http: //⌘.ws или 142.42.1.1 и разрешает http: //.www.foo.bar./, но не зависает, как некоторые другие регулярные выражения, включая ответы с наибольшим рейтингом.
aamarks
@aamarks Я проверил твой ответ. Ваш ответ не отвечает, https://sdfasdp.pppppppppppт. Е. Возвращение, trueно мое возвращение, falseкоторое, я думаю, ожидается.
Викасдип Сингх
4
его возвращение верно для sadf@gmail.com... не так ли? Я думаю, что это не должно быть
Зохаб Али
35

Чтобы проверить URL с помощью JavaScript, показано ниже

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?); б) :{0,1}до :?; в) [0-9]до\d
Дмитрий Паржицкий
28

Положитесь на библиотеку: https://www.npmjs.com/package/valid-url

import { isWebUri } from 'valid-url';
// ...
if (!isWebUri(url)) {
    return "Not a valid url.";
}
Майкл Буш
источник
этот вызывает у меня много проблем со странными URL, которые фактически анализируются браузером, например: наличие {в URL
Willyfrog
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
2
Это потому, что localhost: 8080 не является действительным URL.
Шейн
1
Рабочий образец: runkit.com/shanekenyon87/5bc0e57263c77b0012db05dc
Шейн,
Должно быть 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)работает код Павла. Оба теста имеют идентичные результаты со всеми крайними случаями, которые я тестировал. Мне нравится его код, потому что он проще и не требует создания элементов, но ваш - в несколько раз быстрее (возможно, потому, что он не создает 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/url-regex , а затем isValidURL("https://d1f4470da51b49289906b3d6cbd65074@app.getsentry.com/13176")
завис
Да, как я уже сказал, я просто прокомментировал часть протокола. Я добавил пункт аутентификации для обработки @. Это не висит в моих браузерах .
ко ла
Извините, я прошёл несколько из них, чтобы оценить их, и пропустил, что вы комментировали данный ответ. Я думаю, что ваше исправление даже помогло мне начать с этим, когда я впервые посетил эту страницу. Не висит сейчас.
aamarks
9

Вы можете использовать URL нативного API :

  const isUrl = string => {
      try { return Boolean(new URL(string)); }
      catch(e){ return false; }
  }
Араль Рока
источник
3
Выглядит очень похоже на ответ, предоставленный @pavlo, изменены только имена переменных;)
Munim Munna
2
на самом деле должен быть простой нативный метод, чтобы проверить это - этот ответ выглядел очень многообещающим, но он возвращает истину, как упоминалось выше @Basj.
zero_cool
8

Как уже отмечалось, идеальное регулярное выражение неуловимо, но все же кажется разумным подходом (альтернативы - тесты на стороне сервера или новый экспериментальный URL API ). Однако высокопоставленные ответы часто возвращают false для обычных URL-адресов, но, что еще хуже, ваше приложение / страница замораживается на несколько минут даже при такой простой строке, как isURL('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'). На это было указано в некоторых комментариях, но, скорее всего, для его просмотра не было введено неправильное значение. Такое зависание делает этот код непригодным для использования в любом серьезном приложении. Я думаю, что это связано с повторяющимися нечувствительными к регистру наборами в коде, как ((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.?)+[a-z]{2,}|' .... Выньте «я», и оно не зависнет, но, конечно, не будет работать так, как хотелось бы. Но даже с флагом игнорирования регистра эти тесты отклоняют допустимые высокие значения Юникода.

Лучшее уже упоминалось:

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

Это происходит от Github segmentio / is-url . Хорошая вещь о репозитории кода - вы можете видеть тестирование и любые проблемы, а также тестовые строки, проходящие через него. Есть ветка, которая позволила бы пропустить строки, например google.com, хотя вы, вероятно, делаете слишком много предположений. Хранилище было обновлено, и я не собираюсь пытаться держать зеркало здесь. Это было разбито на отдельные тесты, чтобы избежать повторов RegEx, которые могут быть использованы для DOS-атак (я не думаю, что вам нужно беспокоиться об этом с js на стороне клиента, но вам нужно беспокоиться о том, что ваша страница зависает так долго, что ваш посетитель покидает ваш сайт).

Я видел еще один репозиторий, который может быть даже лучше для isURL в dperini / regex-weburl.js , но он очень сложный. Он имеет больший тестовый список действительных и недействительных URL. Простой выше все еще пропускает все позитивы и не может блокировать только несколько нечетных негативов, таких http://a.b--c.de/как специальные ips.

Независимо от того, что вы выберете, запустите его с помощью этой функции, которую я адаптировал из тестов 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"));}

А затем проверьте эту строку «а».

Посмотрите это сравнение регулярных выражений isURL от Mathias Bynens для получения дополнительной информации, прежде чем публиковать, казалось бы, замечательное регулярное выражение.

aamarks
источник
Я проверил ваш ответ. Ваш ответ не подходит для sdfasdp.ppppppppppp, то есть возвращает значение true, но ожидаемое значение false
Vikasdeep Singh
1
Я думаю, что это правильный URL, структурно. Не эксперт по стандарту, но я не думаю, что есть ограничение на длину части .com (я знаю .online является законным).
aamarks
1
Я едва знал, как написать регулярное выражение пару месяцев назад. Проблема серьезна. Оба приведенных мною регулярных выражения могут выполняться isURL('a'.repeat(100))миллионы раз в секунду (более сложное из dperini на самом деле быстрее). Некоторые из высокопоставленных ответов формы ([a-zA-Z] +) * могут занять несколько часов, чтобы завершить это один раз. Посмотрите RedEx 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
iamnewton
источник
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/... для более тестовых случаев
Kewal Шах
5

Используйте validator.js

ES6

import isURL from 'validator/lib/isURL'

isURL(string)

Нет ES6

var validator = require('validator');

validator.isURL(string)

Вы также можете точно настроить поведение этой функции, передав необязательный optionsобъект в качестве второго аргумента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
Ницца! Небольшая библиотека (менее 40 тыс. Штук), популярная библиотека (более 3 млн. Еженедельных загрузок по npm), дает вам массу гибкости при определении допустимости URL-адресов для вашего конкретного варианта использования и имеет ряд других валидаторов, кроме URL-адреса. Это, безусловно, лучший ответ, ИМХО.
Джавид Джамае
4

Одна функция, которую я использовал для проверки URL-адреса "строка":

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. Например, доменные имена имеют сложные ограничения на дефисы:

    а. Разрешено иметь много последовательных дефисов в середине.

    б. но первый и последний символ имени домена не может быть дефисом

    с. 3-й и 4-й символ не может быть дефисом

  2. Точно так же номер порта может быть только в диапазоне 1-65535. Это легко проверить, если вы извлекаете часть порта и конвертируете в нее, intно довольно сложно проверить с помощью регулярного выражения.

  3. Также нет простого способа проверить действительные доменные расширения. В некоторых странах есть домены второго уровня (например, «co.uk»), или расширение может быть длинным словом, например «.international». И новые TLD добавляются регулярно. Этот тип вещей может быть проверен только по жестко закодированному списку. (см. https://en.wikipedia.org/wiki/Top-level_domain )

  4. Кроме того, существуют URL-адреса, адреса FTP и т. Д. Все они имеют разные требования.

Тем не менее, вот функция, которая обрабатывает почти все, кроме:

  • Случай 1. с
  • Принимает любой 1-5-значный номер порта
  • Принимает любое продление 2-13 символов
  • Не принимает фтп, магнит и т.д ...

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

Я думаю, что использование нативного URL API лучше, чем сложные шаблоны регулярных выражений, как предложил @pavlo. У него есть некоторые недостатки, которые мы можем исправить с помощью дополнительного кода. Этот подход не подходит для следующего действительного 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

Вопрос задает метод проверки для URL, например stackoverflow, без протокола или любой точки в имени хоста. Таким образом, дело не в проверке синтаксиса URL, а в проверке, является ли он действительным, путем его фактического вызова.

Я попробовал несколько способов узнать, существует ли истинный URL и можно ли его вызывать из браузера, но не нашел способа проверить с помощью javascript заголовок ответа на вызов:

  • добавление элемента привязки отлично подходит для запуска click()метода.
  • Выполнение ajax-вызова на вызывающий URL-адрес 'GET'- это хорошо, но оно имеет различные ограничения из-за CORSполитик и не подходит для использования ajax, так как URL-адрес может быть любым за пределами домена моего сервера.
  • использование API извлечения имеет обходной путь, похожий на ajax.
  • Другая проблема заключается в том, что мой сервер работает по httpsпротоколу и выдает исключение при вызове незащищенных URL-адресов.

Итак, лучшее решение, которое я могу придумать, - это заставить некоторый инструмент работать CURLс использованием javascript, пытаясь что-то вроде curl -I <url>. К сожалению, я не нашел ни одного, и на первый взгляд это не возможно. Буду признателен за любые комментарии по этому вопросу.

Но, в конце концов, у меня работает сервер, PHPи, поскольку я использую Ajax почти для всех своих запросов, я написал функцию на стороне сервера, чтобы выполнить там запрос curl и вернуться в браузер.

Что касается отдельного слова url в вопросе «stackoverflow», оно приведет меня к тому https://daniserver.com.ar/stackoverflow, где daniserver.com.ar - мой собственный домен.

Дэниел Фор
источник
ФП, вероятно, должен был указать больше о его намерениях. Эта проблема, безусловно, зависит от ваших потребностей и того, что более важно исключить ложные срабатывания или включить ложные отрицания. Поскольку проблема поставлена, мне, кажется, нет ответа. Можете ли вы взять fooи предположить, что это http или https или .com или .es или какой-либо из бесчисленных суффиксов? Вы продолжаете бросать кухонную раковину в это, пока не получите истинное?
aamarks,
1

Кажется, это одна из самых сложных проблем в CS;)

Вот еще одно неполное решение, которое работает достаточно хорошо для меня и лучше, чем другие, которые я видел здесь. Я использую input [type = url] для этого, чтобы поддержать IE11, иначе было бы намного проще использовать 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, если адрес действителен. Возвращает ложь, когда недействителен.

Он также поддерживает домены IPv4, но не IPv6.

Rosenfeld
источник
1

В моем случае мое единственное требование состоит в том, чтобы пользовательский ввод не интерпретировался как относительная ссылка, если он помещен в href тега, и ответы здесь были либо немного OTT для этого, либо разрешенные URL не соответствуют моим требованиям, поэтому это это то, что я собираюсь с:

^https?://.+$

То же самое может быть достигнуто довольно легко без регулярных выражений.

rdans
источник
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);
}
HeshamSalama
источник
1
Этот ответ уже был дан выше 4 года назад Кавитой Редди.
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

Матиас Биненс составил список известных регулярных выражений URL с тестовыми URL. Нет особых причин писать новое регулярное выражение; просто выберите существующий, который подходит вам лучше всего.

Но таблица сравнения для этих регулярных выражений также показывает, что почти невозможно выполнить проверку URL с помощью одного регулярного выражения. Все регулярные выражения в списке Биненса дают ложные срабатывания и ложные отрицания.

Я предлагаю вам использовать существующий анализатор URL (например, new URL('http://www.example.com/')в JavaScript), а затем применить проверки, которые вы хотите выполнить, к проанализированной и нормализованной форме URL, соответственно. его компоненты. Использование URLинтерфейса JavaScript имеет дополнительное преимущество, заключающееся в том, что он будет принимать только те 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 ни в коем случае не ограничены 4 десятичными целыми числами в диапазоне 0-255. Вы можете использовать от одного до четырех целых чисел, и они могут быть десятичными, восьмеричными или шестнадцатеричными. 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.).
  • Часть имени хоста ссылки может содержать угловые скобки для адресов IPv6, как в http: // [:: 1] .
  • Адреса IPv6 также имеют диапазоны для частных сетей или локальных адресов и т. Д.
  • Если вы блокируете определенные IPv4-адреса, имейте в виду, что, например, https://127.0.0.1 и https: // [:: ffff: 127.0.0.1] указывают на один и тот же ресурс (если устройство обратной связи вашего компьютера готово к IPv6 ).
  • Часть URL-адреса имени хоста теперь может содержать Unicode, так что диапазон символов [-0-9a-zA-z]определенно больше не является достаточным.
  • Многие реестры для доменов верхнего уровня определяют конкретные ограничения, например, для разрешенного набора символов Юникода. Или они подразделяют свое пространство имен (как co.ukи многие другие).
  • Домены верхнего уровня не должны содержать десятичных цифр, и дефис не допускается, если только для префикса метки A IDN "xn--".
  • Домены верхнего уровня в Юникоде (и их кодировку с помощью «xn--»), все еще должны содержать только буквы, но кто хочет проверить это в регулярном выражении?

Какие из этих ограничений и правил применяются, зависит от требований и вкуса проекта.

Недавно я написал валидатор URL-адресов для веб-приложения, которое подходит для пользовательских 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

Вот только очень простая проверка, чтобы убедиться, что есть действительный протокол, и расширение домена должно состоять из двух или более символов.

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;  
    }
}
greg.arnott
источник
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');
}

Источник

Бруно Фингер
источник