Есть ли в JavaScript способ проверить, является ли строка URL-адресом?
RegExes исключены, потому что URL, скорее всего, написан как stackoverflow
; то есть он может не иметь .com
, www
или http
.
Есть ли в JavaScript способ проверить, является ли строка URL-адресом?
RegExes исключены, потому что URL, скорее всего, написан как stackoverflow
; то есть он может не иметь .com
, www
или http
.
Смежный вопрос с ответом:
Соответствие 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);
}
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);
}
Вместо использования регулярного выражения я бы рекомендовал использовать якорный элемент.
когда вы устанавливаете свойство 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);
}
Вы можете попробовать использовать URL
конструктор: если он не выбрасывает, строка является допустимым URL:
const isValidUrl = (string) => {
try {
new URL(string);
return true;
} catch (_) {
return false;
}
}
Термин "URL" определен в RFC 3886 (как URI); оно должно начинаться с имени схемы, а имя схемы не ограничивается http/https.
Известные примеры:
www.google.com
недействительный URL (отсутствует схема)javascript:void(0)
является действительным URL, но не HTTPhttp://..
является допустимым URL-адресом, где хостом является ..
; разрешается ли он, зависит от вашего DNShttps://google..com
действительный URL, такой же как выше Я использую функцию ниже для проверки URL с или без http/https
:
function isValidURL(string) {
var res = string.match(/(http(s)?:\/\/.)?(www\.)?[[email protected]:%._\+~#=]{2,256}\.[a-z]{2,6}\b([[email protected]:%_\+.~#?&//=]*)/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
Чтобы проверить 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;
}
}
Полагайтесь на библиотеку: https://www.npmjs.com/package/valid-url
import { isWebUri } from 'valid-url';
// ...
if (!isWebUri(url)) {
return "Not a valid url.";
}
Улучшение принятого ответа...
Позволяет символ @в пути, например, 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);
}
Вот еще один метод.
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'));
(У меня нет представителей, чтобы комментировать пример ValidURL; поэтому опубликуйте это как ответ.)
Хотя использование относительных к протоколу URL не рекомендуется (относящиеся к протоколу URL), они иногда работают. Чтобы проверить такой URL с помощью регулярного выражения, часть протокола может быть необязательной, например:
function isValidURL(str) {
var pattern = new RegExp('^((https?:)?\\/\\/)?'+ // protocol
'(?:\\S+(?::\\S*)[email protected])?' + // 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-адресов.
Я не могу прокомментировать сообщение, которое является ближайшим # 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
Как уже отмечалось, идеальное регулярное выражение неуловимо, но все же кажется разумным подходом (альтернативы - тесты на стороне сервера или новый экспериментальный URL API). Однако высокопоставленные ответы часто возвращают false для обычных URL-адресов, но, что еще хуже, ваше приложение/страница будет isURL('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')
на несколько минут даже на такой простой строке, как isURL('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')
. На это было указано в некоторых комментариях, но, скорее всего, для его просмотра не было введено неправильное значение. Такое зависание делает этот код непригодным для использования в любом серьезном приложении. Я думаю, что из-за повторяющихся нечувствительных к регистру множеств в коде, как ((([az\\d]([az\\d-]*[az\\d])*)\\.?)+[az]{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://ab--c.de/
а также специальные ips.
Независимо от того, что вы выберете, запустите его через эту функцию, которую я адаптировал из тестов dperini/regex-weburl.js, используя в вашем браузере Inpector Developer Tools.
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:[email protected]:8080"));
console.assert(isURL("http://userid:[email protected]:8080/"));
console.assert(isURL("http://[email protected]"));
console.assert(isURL("http://[email protected]/"));
console.assert(isURL("http://[email protected]:8080"));
console.assert(isURL("http://[email protected]:8080/"));
console.assert(isURL("http://userid:[email protected]"));
console.assert(isURL("http://userid:[email protected]/"));
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:[email protected]:5702/db"));
console.assert(isURL("https://[email protected]/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 для получения дополнительной информации, прежде чем публиковать, казалось бы, замечательное регулярное выражение.
Вы можете использовать собственный API URL:
const isUrl = string => {
try { return Boolean(new URL(string)); }
catch(e){ return false; }
}
Одна функция, которую я использовал для проверки 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
Это довольно сложно сделать с чистым регулярным выражением, потому что URL-адреса имеют много "неудобств".
Например, доменные имена имеют сложные ограничения на дефисы:
а. Разрешено иметь много последовательных дефисов в середине.
б. но первый и последний символ имени домена не может быть дефисом
с. 3-й и 4-й символ не может быть дефисом
Точно так же номер порта может быть только в диапазоне 1-65535. Это легко проверить, если вы извлекаете часть порта и конвертируете в int
но довольно сложно проверить с помощью регулярного выражения.
Также нет простого способа проверить действительные доменные расширения. В некоторых странах есть домены второго уровня (например, "co.uk"), или расширение может быть длинным словом, например ".international". И новые TLD добавляются регулярно. Этот тип вещей может быть проверен только по жестко закодированному списку. (см. https://en.wikipedia.org/wiki/Top-level_domain)
Кроме того, существуют URL-адреса, адреса 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] + ']');
}
Вопрос задает метод проверки для URL-адреса, такого как stackoverflow
, без протокола или какой-либо точки в имени хоста. Таким образом, дело не в проверке синтаксиса URL, а в проверке, является ли он действительным, путем его фактического вызова.
Я попробовал несколько способов узнать, существует ли URL-адрес истина и может ли он вызываться из браузера, но не нашел способа проверить с помощью javascript заголовок ответа на вызов:
click()
.'GET'
хорошо, но он имеет различные ограничения из-за политик CORS
, и это не тот случай использования ajax
, поскольку в качестве URL может быть любой другой домен вне моего сервера.https
и выдает исключение при вызове незащищенных URL-адресов. Итак, лучшее решение, которое я могу придумать, - это получить какой-нибудь инструмент для выполнения CURL
с использованием javascript, попробовав что-то вроде curl -I <url>
. К сожалению, я не нашел ни одного и на первый взгляд это невозможно. Буду признателен за любые комментарии по этому вопросу.
Но, в конце концов, у меня есть сервер, на котором работает PHP
и, поскольку я использую Ajax почти для всех своих запросов, я написал функцию на стороне сервера, чтобы выполнить там запрос curl и вернуться в браузер.
Что касается отдельного слова url в вопросе "stackoverflow", это приведет меня к https://daniserver.com.ar/stackoverflow
, где daniserver.com.ar - мой собственный домен.
В моем случае мое единственное требование состоит в том, чтобы пользовательский ввод не интерпретировался как относительная ссылка, если он помещен в href тега, и ответы здесь были либо немного OTT для этого, либо разрешенные URL не соответствуют моим требованиям, поэтому это это то, что я собираюсь с:
^https?://.+$
То же самое может быть достигнуто довольно легко без регулярных выражений.
это работает со мной
function isURL(str) {
var regex = /(http|https):\/\/(\w+:{0,1}\w*)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%!\-\/]))?/;
var pattern = new RegExp(regex);
return pattern.test(str);
}
Если вы можете изменить тип ввода, я думаю, что это решение будет намного проще:
Вы можете просто использовать 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
}
});
Это демонстративно не самый эффективный подход, но он легко читается и легко поддается формированию. И здесь проще добавить регулярное выражение/сложность. Так что здесь очень прагматичный подход
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 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;
}
TEST:
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);
});
});
});
Я думаю, что использование нативного 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 и надеюсь, что он начнет поддерживать все в ближайшем будущем.
Кажется, это одна из самых сложных проблем в 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:[email protected]'),
validateUrl('https://google.com'),
validateUrl('100.100.100.100/abc'),
validateUrl('100.100.100.256/abc')); // false
Здесь просто очень простая проверка, чтобы убедиться в наличии действующего протокола, а расширение домена должно состоять из двух или более символов.
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
);
};
Используйте 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