Проверьте, является ли строка Javascript url-адресом


есть ли способ в javascript проверить, является ли строка url-адресом?

регулярные выражения исключаются, потому что url-адрес, скорее всего, написан как stackoverflow; то есть он может не иметь .com, www или http

17 133

17 ответов:

связанный вопрос с ответом:

в 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 locater
  if(!pattern.test(str)) {
    alert("Please enter a valid URL.");
    return false;
  } else {
    return true;
  }
}
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-адресу, тогда значение этих вспомогательных свойств будет пустой строкой.

Edit: как указано в комментариях: если используется недопустимый 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 с помощью 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;
  }
}

улучшение принятого ответа...

  • имеет двойной побег для обратной косой черты (\\)
  • гарантирует, что домены имеют точку и расширение (. 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('^(https?:\/\/)?'+ // 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);
    }
    

полагаться на библиотеки: https://www.npmjs.com/package/valid-url

import { isWebUri } from 'valid-url';
// ...
if (!isWebUri(url)) {
    return "Not a valid url.";
}

(У меня нет представителей, чтобы комментировать 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-адресов.

Я использую ниже функцию для проверки 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);
  if (res == null)
    return false;
  else
    return true;
};

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

вот еще один метод.

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'));

Я не могу прокомментировать сообщение, которое является самым близким #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'). Это было отмечено в некоторых комментариях, но скорее всего не ввели неверное значение, чтобы увидеть его. Висит так, что делает этот код непригоден для использования в любом серьезном приложении. Я думаю, что это из-за повторяющихся нечувствительных к регистру наборов в коде, таких как ((([a-z\d]([a-z\d-]*[a-z\d])*)\.?)+[a-z]{2,}|' .... Выньте "я", и он не висит, но, конечно, не будет работать по желанию. Но даже с флагом ignore case эти тесты отклоняют допустимые высокие значения Юникода.

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

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

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

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

что бы вы ни выбрали, запустите его через это функция, которую я адаптировал из тестов на dperini / regex-weburl.js, при использовании инструментов разработчика Вашего браузера inpector.

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 Матиас Байненс для получения дополнительной информации, прежде чем опубликовать, казалось бы, большое регулярное выражение.

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

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 native API:

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

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

я попробовал несколько методов, чтобы узнать, существует ли url true и вызывается из браузера, но не нашел способа проверить с помощью javascript заголовок ответа вызова:

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

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

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

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

Я думаю, используя родной 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;
    }
}

The hostname атрибут является пустой строкой для javascript:void(0), так что это тоже работает, и вы также можете добавить верификатор IP-адреса тоже. Я хотел бы придерживаться собственного API больше всего, и надеюсь, что он начнет поддерживать все в ближайшем будущем.

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

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