Sprawdź, czy ciąg JavaScript jest adresem URL


284

Czy w JavaScript jest sposób sprawdzenia, czy ciąg znaków jest adresem URL?

RegExes są wykluczone, ponieważ adres URL jest najprawdopodobniej zapisany jak stackoverflow; to znaczy, że może nie mieć .com, wwwlub http.


22
Jeśli go brakuje http, domyślnie nie ma adresu URL.
nfechner

1
@ nfechner, to znaczy, że jeśli nie określa protokołu i nie używa znaku dwukropka (najlepiej z następnymi dwoma ukośnikami), to nie jest to adres URL?
jcolebrand

5
Jak można przeczytać w RFC adresu URL , jedyną częścią, która jest niezbędna, aby napis String był prawidłowym adresem URL, jest dwukropek. Prawidłowe adresy URL wyglądają następująco:<scheme>:<scheme-specific-part>
nfechner


8
Sposób testowania, czy coś jest adresem URL, jest wysoce zależny od kontekstu i zbyt niejasny bez dalszych kwalifikacji. Czy ma znaczenie, czy jest zgodny ze specyfikacją RFC adresu URL, działa podczas wykonywania wywołania systemowego w celu otwarcia adresu URL , analizuje jako hrefelement kotwiczący, działa podczas wywoływania window.open(url), wskazuje na coś, co naprawdę istnieje, działa w lokalizacji przeglądarki pasek lub kombinacja powyższych? Uzyskasz bardzo różne odpowiedzi w zależności od tego, na czym Ci zależy.
Roy Tinker,

Odpowiedzi:


189

Powiązane pytanie z odpowiedzią:

Dopasowywanie wyrażeń regularnych JavaScript

Lub ten Regexp z 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
Wiem, ale szukam w moich zakładkach i większość z nich jest napisana jak stackoverflow (bez .com, itp.)
Bruno,

3
@Bruno: jest bardzo prawdopodobne, że są one wewnętrznie zapisywane z osobnymi tytułami i adresami URL, takimi jak { title: "Stackoverflow", uri: "http://stackoverflow.com" } Aktualizacja: rzeczywiście, zobacz code.google.com/chrome/extensions/bookmarks.html
Marcel Korpel

10
próbując użyć twojego przykładu. Ale pojawia się błąd w Firebug, który mówi invalid quantifier. Dowolny pomysł?
Sisir,

125
Zwraca funkcję: 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 (wersja 30.0.1599.101) (Mac OS X: 10.8.5)
dr.dimitru 19.10.2013

10
Pamiętaj, że jeśli użyjesz łańcucha jako parametru RegExp, musisz podwójnie uciec z ukośników odwrotnych - w przeciwnym razie otrzymasz błędy, takie jak nieprawidłowa grupa .
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
nie działa w wyszukiwarce Google linki do obrazów: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
Bill David

7
jest to bezużyteczne wolne
Hernán Eche

3
@ HernánEche Co masz na myśli przez slow ? start = new Date(); isURL("http://michalstefanow.com"); end = new Date(); diff = end - start; console.log(diff)Włączyłem czajnik, poszedłem do toalety, zadzwoniłem do mamy, a sprawa została wykonana w
Mars Robertson

62
Wraca trueza aaa.
alex naumov

1
To absolutnie nie powinna być poprawna odpowiedź. Nie udaje się wielu testom, a co ważniejsze, zawiesza twoją stronę nawet na krótkim łańcuchu: isURL('12345678901234567890123')dodaj kilka znaków, a nawet gorzej.
aamarks

142

Możesz spróbować użyć URLkonstruktora : jeśli nie wyrzuca, ciąg jest prawidłowym adresem URL:

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

  return true;
}

Termin „URL” jest zdefiniowany w RFC 3886 (jako URI); musi zaczynać się od nazwy schematu, a nazwa schematu nie ogranicza się do http / https.

Godne uwagi przykłady:

  • www.google.com jest nieprawidłowy adres URL (brak schematu)
  • javascript:void(0) jest prawidłowym adresem URL, chociaż nie jest adresem HTTP
  • http://..jest prawidłowym adresem URL, przy czym host jest ..; to, czy zostanie rozwiązane, zależy od Twojego DNS
  • https://google..com jest prawidłowym adresem URL, takim samym jak powyżej

Jeśli chcesz sprawdzić, czy ciąg jest prawidłowym adresem URL HTTP:

function isValidHttpUrl(string) {
  let url;

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

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

13
@AshD nie, to nie jest; np. nie możesz użyć jako hrefatrybutu dla <a>. Prawidłowy adres URL musi zaczynać się od nazwy schematu , np https://.
Pavlo

3
nowy adres URL („javascript: alert (23)”)
blade091

6
@Pavlo zwraca wartość trueisValidUrl("javascript:void(0)")
Praveena

3
Lubię to za uczenie mnie nowych rzeczy na temat js! Nie ma w nim fałszywych negatywów. Ma kilka fałszywych trafień: http://..lubhttp:///a
aamarks

2
Adres URL działa, zaczynając od Edge, więc wszystko pod nim może nie działać zgodnie z oczekiwaniami. Najpierw sprawdź zgodność.
Tony T.

97

Zamiast używać wyrażenia regularnego, zaleciłbym użycie elementu kotwicy.

po ustawieniu hrefwłaściwości an anchorustawiane są różne inne właściwości.

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"

źródło

Jeśli jednak wartość hrefjest powiązana z niepoprawnym adresem URL, wartością tych właściwości pomocniczych będzie pusty ciąg.

Edycja: jak wskazano w komentarzach: w przypadku użycia nieprawidłowego adresu URL właściwości bieżącego adresu URL mogą zostać podstawione.

Tak długo, jak nie podajesz adresu URL bieżącej strony, możesz zrobić coś takiego:

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

3
Tak nie jest (przynajmniej w Chrome 48). Jeśli przekazany adres URL a.hrefjest nieprawidłowy, parser.hostzwraca nazwę hosta strony, na której aktualnie się znajdujesz, a nie oczekiwaną false.
Sam Beckham,

2
Gah! to jest dziwne. Przysięgam, że to przetestowałem! Myślę, że można śmiało powiedzieć, że tak naprawdę nigdy nie będzie trzeba jej używać na bieżącej stronie, więc warunki można po prostu zmienić. Zmienię post.
Łukasz

nie jest to bardzo typowy przypadek użycia, ale ta technika nie działa w kontekście okna przeglądarki Firefox (ważna dla rozwoju dodatków)
chrmod

@SamBeckham Jest to z pewnością problem podczas korzystania z tej metody, ale chcę tylko podkreślić, że nie jest to specjalne zachowanie. Jeśli masz link na swojej stronie, które jest nieważne, jak <a href="invalidurl">to ma iść do swojej domeny. Zostaje dodany na końcu bieżącego adresu URL. Chrome działa prawidłowo, podając bieżącą nazwę hosta z elementu „parser”.
YTS

4
function isValidURL(str): o wiele lepsze niż użycie wyrażenia regularnego! Dziękuję Ci!
Rodrigo

47

Korzystam z poniższej funkcji do sprawdzania poprawności adresu URL z lub bez 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
Wygląda na fajne rozwiązanie! Czy możesz dodać kilka testów pokazujących, że działa w niektórych przypadkach narożnych (patrz na przykład te komentarze )?
Basj

@Basj dodał przypadki testowe. Proszę sprawdzić
Vikasdeep Singh

Nieźle, nie przechodzi http: //⌘.ws lub 142.42.1.1 i pozwala http: //.www.foo.bar./, ale nie zawiesza się jak niektóre inne wyrażenia regularne, w tym najwyżej ocenione odpowiedzi.
aamarks

@aamarks Sprawdziłem twoją odpowiedź. Twoja odpowiedź jest nieudana, https://sdfasdp.ppppppppppptzn. truePowraca, ale moim falsezdaniem oczekiwane są zwroty .
Vikasdeep Singh

4
powraca prawda dla sadf@gmail.com... czy powinna? Myślę, że nie powinno
Zohab Ali

35

Aby sprawdzić poprawność adresu URL za pomocą javascript, pokazano poniżej

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
Kilka części wyrażenia regularnego można znacznie zredukować: a) (http|https)do (?:https?); b) :{0,1}do :?; c) [0-9]do\d
Dmitrij Parzhitsky


23

Poprawa przyjętej odpowiedzi ...

  • Sprawdź ftp / ftps jako protokół
  • Ma podwójne znaki ucieczki dla odwrotnych ukośników (\\)
  • Zapewnia, że ​​domeny mają kropkę i rozszerzenie (.com .io .xyz)
  • Umożliwia pełne dwukropek (:) na ścieżce, np. Http://thingiverse.com/download:1894343
  • Zezwala na wstawianie ampersand (&) np. Http://en.wikipedia.org/wiki/Procter_&_Gamble
  • Pozwala na symbol @ na ścieżce, np. 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
Nie, to nie powinna być zaakceptowana odpowiedź. Podobnie jak niektóre inne, zawiesza się na ciągu 33 znaków: isURL ('123456789012345678901234567890123') i nie przejdzie wielu testów wielkości krawędzi: foo.com/blah_blah_(wikipedia)_ ( znowu)) niepoprawnie zwraca false.
aamarks

2
Jest tak, ponieważ localhost: 8080 nie jest prawidłowym adresem URL.
Shane,


Powinien być ftps: // localhost: 8080 =)
vp_arth 10.02.19

Wydaje się, że to nie działa: zawiesza się na długim wejściu (jak powiedział @aanmarks)
cecemel

13

Oto kolejna metoda.

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


Kod edukacyjny! Mechanizm tutaj jest prawdopodobnie identyczny jak new URL(string)w kodzie Pavlo. Oba testy mają identyczne wyniki ze wszystkimi testowanymi przypadkami krawędzi. Podoba mi się jego kod, ponieważ jest prostszy i nie wymaga tworzenia elementów, ale twój jest kilka razy szybszy (prawdopodobnie dlatego, że nie tworzy el po pierwszym użyciu).
aamarks,

1
Dziękuję Ci! Wdrożyłem twoją radę. Pamiętaj jednak: starsze przeglądarki i / lub urządzenia mobilne WebView mogły nie implementować elementu <input type = url>; dlatego wartość wejściowa byłaby traktowana jak zwykły tekst (bez sprawdzania poprawności adresu URL).
ODNIESIENIE

10

(Nie mam powtórzeń, by komentować ValidURL przykład ; dlatego opublikuj to jako odpowiedź).

Chociaż stosowanie adresów URL względnych dla protokołu nie jest zalecane ( adres URL względny dla protokołu ), czasami się angażują. Aby zweryfikować taki adres URL za pomocą wyrażenia regularnego, część protokołu może być opcjonalna, np .:

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;
    }
}

Jak zauważyli inni, wyrażenie regularne nie wydaje się być najlepszym rozwiązaniem do sprawdzania poprawności adresów URL.


Na początku myślałem, że to całkiem niezłe, ale nie udaje się wiele testów w mathiasbynens.be/demo/url-regex , a potem się zawieszaisValidURL("https://d1f4470da51b49289906b3d6cbd65074@app.getsentry.com/13176")
aamarks

Tak, jak powiedziałem, po prostu skomentowałem część protokołu. Dodałem klauzulę uwierzytelnienia do obsługi @. Nie zawiesza się w moich przeglądarkach .
ko la

Przepraszam, przejrzałem kilka z nich, aby je ocenić i przegapiłem, że twój komentuje podaną odpowiedź. Myślę, że twoja korekta pomogła mi nawet zacząć od nich, kiedy pierwszy raz odwiedziłem tę stronę. Teraz nie wisi.
aamarks,

9

Możesz użyć natywnego API URL :

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

3
Wygląda bardzo podobnie do odpowiedzi udzielonej przez @pavlo, zmieniono tylko nazwy zmiennych;)
Munim Munna

2
naprawdę powinna istnieć prosta, natywna metoda, aby to sprawdzić - ta odpowiedź wyglądała bardzo obiecująco, ale zwraca wartość prawda wcześnie, jak wspomniano powyżej @Basj.
zero_cool

8

Jak zauważono, idealne wyrażenie regularne jest nieuchwytne, ale nadal wydaje się rozsądnym podejściem (alternatywą są testy po stronie serwera lub nowy eksperymentalny interfejs API URL ). Jednak odpowiedzi o wysokiej pozycji często zwracają wartość false dla typowych adresów URL, ale nawet gorzej zamraża aplikację / stronę na kilka minut nawet na tak prostym ciągu jak isURL('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'). Zostało to wskazane w niektórych komentarzach, ale najprawdopodobniej nie wprowadzono złej wartości, aby to zobaczyć. Takie zawieszenie sprawia, że ​​ten kod nie nadaje się do użytku w żadnej poważnej aplikacji. Myślę, że jest to spowodowane powtarzającymi się zestawami bez rozróżniania wielkości liter w kodzie((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.?)+[a-z]{2,}|' ... . Wyjmij „i” i nie zawiesza się, ale oczywiście nie będzie działać zgodnie z oczekiwaniami. Ale nawet z flagą ignorowania przypadków testy te odrzucają wysokie dopuszczalne wartości Unicode.

Najlepiej już wspomniane to:

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

To pochodzi z Github segmentio / is-url . Zaletą repozytorium kodu jest to, że można zobaczyć testy i wszelkie problemy, a także ciągi testowe przez nie przechodzące. Istnieje gałąź, która pozwalałaby na brakujące ciągi znaków google.com, chociaż prawdopodobnie przyjmujesz wtedy zbyt wiele założeń. Repozytorium zostało zaktualizowane i nie planuję tutaj utrzymywać kopii lustrzanej. Został on podzielony na osobne testy, aby uniknąć powtórzeń RegEx, które można wykorzystać do ataków DOS (nie sądzę, że musisz się tym martwić js po stronie klienta, ale musisz martwić się o zawieszenie strony tak długo, że odwiedzający opuszcza Twoją witrynę).

Jest jeszcze jedno repozytorium, które widziałem, które może być nawet lepsze dla isURL na dperini / regex-weburl.js , ale jest bardzo złożone. Ma większą listę testową prawidłowych i nieprawidłowych adresów URL. Prosty powyżej nadal przekazuje wszystkie pozytywy i nie blokuje tylko kilku dziwnych negatywów, takich http://a.b--c.de/jak specjalne IPS.

Niezależnie od tego, co wybierzesz, uruchom go za pomocą tej funkcji, którą zaadaptowałem z testów na dperini / regex-weburl.js, podczas korzystania z narzędzia programistycznego przeglądarki.

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 następnie przetestuj ciąg „a”.

Zobacz to porównanie wyrażenia regularnego isURL autorstwa Mathiasa Bynensa, aby uzyskać więcej informacji przed opublikowaniem pozornie doskonałego wyrażenia regularnego.


Sprawdziłem twoją odpowiedź. Twoja odpowiedź jest nieudana w przypadku sdfasdp.ppppppppppp, tzn. Zwracanie wartości true, ale oczekiwane jest fałszywe
Vikasdeep Singh

1
Wydaje mi się, że jest to prawidłowy URL, strukturalnie. Nie jestem ekspertem od standardu, ale nie sądzę, że istnieje limit długości części .com (wiem, że .online jest legalny).
aamarks

1
Kilka miesięcy temu ledwo wiedziałem, jak napisać wyrażenie regularne. Problem jest poważny. Oba cytowane isURL('a'.repeat(100))przeze mnie wyrażenie regularne może wykonać miliony razy na sekundę (bardziej złożony z dperini jest w rzeczywistości szybszy). Niektóre z wysoko postawionych odpowiedzi w formularzu ([a-zA-Z] +) * zajęłyby kilka godzin. Aby uzyskać więcej informacji, wyszukaj redos RegEx.
aamarks,

6

Nie mogę komentować postu, który jest najbliższy # 5717133 , ale poniżej znajduje się sposób, w jaki wymyśliłem, jak uruchomić regex @ tom-gullen.

/^(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
To działało dla mnie, ale musiałem wykonać ukośnik odwrotny. 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');
Fernando Chavez Herrera

Sprawdź w3resource.com/javascript-exercises/ ... więcej przypadków testowych
Kewal Shah

5

Użyj validator.js

ES6

import isURL from 'validator/lib/isURL'

isURL(string)

Brak ES6

var validator = require('validator');

validator.isURL(string)

Możesz także dostroić zachowanie tej funkcji, przekazując opcjonalny optionsobiekt jako drugi argumentisURL

Oto domyślny optionsobiekt:

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_whitelisti host_blacklistmogą być tablicami hostów. Obsługują również wyrażenia regularne.

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
Miły! Mała biblioteka (mniej niż 40 000), popularna biblioteka (ponad 3 miliony cotygodniowych pobrań na npm), daje mnóstwo elastyczności w określaniu poprawności adresów URL dla konkretnego przypadku użycia i ma wiele innych walidatorów oprócz URL. To zdecydowanie najlepsza odpowiedź, IMHO.
Javid Jamae

4

Jedną funkcją, której używałem do sprawdzania poprawności „ciągu” adresu URL jest:

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

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

Ta funkcja zwraca wartość logiczną, czy ciąg jest adresem URL.

Przykłady:

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

Jest to dość trudne w przypadku zwykłego wyrażenia regularnego, ponieważ adresy URL mają wiele „niedogodności”.

  1. Na przykład nazwy domen mają skomplikowane ograniczenia dotyczące łączników:

    za. W środku może znajdować się wiele kolejnych łączników.

    b. ale pierwszy znak i ostatni znak nazwy domeny nie mogą być łącznikiem

    do. Trzeci i czwarty znak nie mogą być jednocześnie łącznikiem

  2. Podobnie numer portu może zawierać się w zakresie 1-65535. Łatwo to sprawdzić, jeśli wyodrębniasz część portu i konwertujesz na, intale dość trudno jest sprawdzić za pomocą wyrażenia regularnego.

  3. Nie ma również łatwego sposobu sprawdzenia prawidłowych rozszerzeń domen. Niektóre kraje mają domeny drugiego poziomu (takie jak „co.uk”) lub rozszerzenie może być długim słowem, np. „.International”. Nowe domeny TLD są dodawane regularnie. Tego rodzaju rzeczy można sprawdzić tylko na liście zakodowanej na stałe. (patrz https://en.wikipedia.org/wiki/Top-level_domain )

  4. Następnie są adresy URL magnesów, adresy ftp itp. Wszystkie mają różne wymagania.

Niemniej jednak, tutaj jest funkcja, która obsługuje prawie wszystko oprócz:

  • Przypadek 1. c
  • Akceptuje dowolny 1-5-cyfrowy numer portu
  • Akceptuje dowolne rozszerzenia 2-13 znaków
  • Nie akceptuje ftp, magnesu itp.

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

Myślę, że używanie natywnego interfejsu API URL jest lepsze niż złożone wzorce wyrażeń regularnych, jak sugerował @pavlo. Ma jednak pewne wady, które możemy naprawić za pomocą dodatkowego kodu. To podejście kończy się niepowodzeniem dla następującego prawidłowego adresu URL.

//cdn.google.com/script.js

Możemy wcześniej dodać brakujący protokół, aby tego uniknąć. Nie wykrywa również następującego nieprawidłowego adresu URL.

http://w
http://..

Po co więc sprawdzać cały adres URL? możemy po prostu sprawdzić domenę. Pożyczyłem wyrażenie regularne, aby zweryfikować domenę stąd .

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;
    }
}

hostnameAtrybut jest pusty ciąg dla javascript:void(0), tak to działa na to zbyt, można również dodać adres IP weryfikator też. Chciałbym trzymać się najbardziej natywnego API i mam nadzieję, że zacznie on obsługiwać wszystko w najbliższej przyszłości.


Interesujące, ale może nadal wymagać poprawienia wyrażenia regularnego, ponieważ wprowadzono w nim fałszywe negatywy, których new URLnie ma w testach, które przeprowadziłem. To się nazywa: http://142.42.1.1 //falsei blokuje wysokie ciągi Unicode.
aamarks

1

Pytanie wymaga metody sprawdzania adresu URL, na przykład stackoverflowbez protokołu lub kropki w nazwie hosta. Tak więc nie jest to kwestia sprawdzania poprawności adresu URL sintax, ale sprawdzenie, czy jest to prawidłowy adres URL, przez jego wywołanie.

Próbowałem kilku metod, aby dowiedzieć się, czy adres URL true istnieje i można wywołać go z poziomu przeglądarki, ale nie znalazłem żadnego sposobu na przetestowanie za pomocą javascript nagłówka odpowiedzi wywołania:

  • dodanie elementu kotwicy jest odpowiednie do odpalenia click()metody.
  • Wykonywanie wywołań ajax do wymagającego adresu URL 'GET'jest w porządku, ale ma różne ograniczenia ze względu na CORSzasady i nie jest tak w przypadku używania ajax, ponieważ jako adres URL może być dowolny poza domeną mojego serwera.
  • używanie interfejsu API pobierania ma obejście podobne do ajax.
  • innym problemem jest to, że mam mój serwer pod httpsprotokołem i zgłasza wyjątek podczas wywoływania niezabezpieczonych adresów URL.

Tak więc najlepszym rozwiązaniem, jakie mogę wymyślić, jest uzyskanie jakiegoś narzędzia do wykonania CURLza pomocą javascript próbującego czegoś takiego curl -I <url>. Niestety nie znalazłem żadnego, a z wyglądu nie jest to możliwe. Będę wdzięczny za wszelkie komentarze na ten temat.

Ale w końcu mam uruchomiony serwer PHP i ponieważ używam Ajax do prawie wszystkich moich żądań, napisałem funkcję po stronie serwera, aby wykonać tam żądanie curl i wrócić do przeglądarki.

Odnośnie do pojedynczego słowa url w pytaniu „stackoverflow” doprowadzi mnie do https://daniserver.com.ar/stackoverflow, gdzie daniserver.com.ar to moja własna domena.


OP prawdopodobnie powinien był wskazać więcej na jego zamiary. Problem z pewnością różni się w zależności od potrzeb i od tego, czy ważniejsze jest wykluczenie fałszywych trafień, czy fałszywych negatywów. Jak stwierdzono problem, wydaje mi się, że nie ma odpowiedzi. Czy naprawdę możesz przyjąć fooi założyć, że jest to http, https, .com lub .es lub którykolwiek z niezliczonych przyrostków? Czy rzucasz w nią zlewem kuchennym, dopóki nie osiągniesz prawdy?
aamarks

1

To wydaje się być jednym z najtrudniejszych problemów w CS;)

Oto inne niepełne rozwiązanie, które działa wystarczająco dobrze dla mnie i lepiej niż inne, które tu widziałem. Korzystam z danych wejściowych [type = url] w celu obsługi IE11, w przeciwnym razie byłoby znacznie prostsze przy użyciu window.URL, aby zamiast tego wykonać sprawdzenie poprawności:

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

Aby zaakceptować niekompletne dane wejściowe, takie jak „www.moja_domena.com”, spowoduje to również, że będzie on prawidłowy, zakładając, że w tych przypadkach protokół ma wartość „http”, i zwróci prawidłowy adres URL, jeśli adres jest prawidłowy. Zwraca false, gdy jest nieprawidłowy.

Obsługuje także domeny IPv4, ale nie obsługuje IPv6.


1

W moim przypadku moim jedynym wymaganiem jest to, aby dane wejściowe użytkownika nie były interpretowane jako link względny po umieszczeniu w href tagu, a odpowiedzi tutaj były albo trochę OTT dla tego lub dozwolone adresy URL niespełniające moich wymagań, więc to z tym idę:

^https?://.+$

To samo można osiągnąć dość łatwo bez wyrażenia regularnego.


1

to działa ze mną

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
Ta odpowiedź została już podana ponad 4 lata temu przez Kavitha Reddy.
aamarks

po prostu uczyniłem to prostszym i bardziej abstrakcyjnym
HeshamSalama

1

Jeśli możesz zmienić typ danych wejściowych, myślę, że to rozwiązanie byłoby znacznie łatwiejsze:

Możesz w prosty sposób użyć type="url"danych wejściowych i sprawdzić je za pomocą checkValidity()js

Na przykład:

twoja.html

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

twoja.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

To zdecydowanie nie jest najskuteczniejsze podejście, ale jest czytelne i łatwe do sformułowania według potrzeb. Łatwiej jest stąd dodać wyrażenie regularne / złożoność. Oto bardzo pragmatyczne podejście

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;
}

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

1

Mathias Bynens opracował listę znanych wyrażeń regularnych adresów URL z URL testowych. Nie ma powodu, aby pisać nowe wyrażenie regularne; wybierz istniejący, który najbardziej Ci odpowiada.

Ale tabela porównawcza dla tych wyrażeń regularnych pokazuje również, że sprawdzenie poprawności adresu URL za pomocą pojedynczego wyrażenia regularnego jest prawie niemożliwe. Wszystkie wyrażenia regularne na liście Bynensa produkują fałszywie pozytywne i fałszywe negatywy.

Sugeruję użycie istniejącego parsera adresów URL (na przykład new URL('http://www.example.com/') w JavaScript), a następnie zastosowanie sprawdzeń, które chcesz wykonać, względem przeanalizowanej i znormalizowanej formy adresu URL lub. jego składniki. Korzystanie z URLinterfejsu JavaScript ma tę dodatkową zaletę, że akceptuje tylko takie adresy URL, które są naprawdę akceptowane przez przeglądarkę.

Należy również pamiętać, że technicznie niepoprawne adresy URL mogą nadal działać. Na przykład http://w_w_w.example.com/, http://www..example.com/,http://123.example.com/ mają nieprawidłową część hosta ale każda przeglądarka wiem spróbuje otworzyć je bez zarzutów, a kiedy określenia adresów IP dla tych nieprawidłowych nazw w/etc/hosts/ tych adresów URL będzie jeszcze działać, ale tylko na komputerze.

Dlatego nie chodzi o to, czy adres URL jest prawidłowy, ale o to, które adresy URL działają i powinny być dozwolone w określonym kontekście.

Jeśli chcesz przeprowadzić weryfikację adresu URL, istnieje wiele szczegółów i przypadków, które można łatwo przeoczyć:

  • Adresy URL mogą zawierać dane uwierzytelniające jak w http://user:password@www.example.com/ .
  • Numery portów muszą zawierać się w przedziale 0–65535, ale nadal możesz wykluczyć port wieloznaczny 0.
  • Numery portów mogą mieć początkowe zera, jak w http://www.example.com:000080/ .
  • Adresy IPv4 w żadnym wypadku nie są ograniczone do 4 liczb dziesiętnych w zakresie 0–255. Możesz użyć od jednej do czterech liczb całkowitych, które mogą być dziesiętne, ósemkowe lub szesnastkowe. Wszystkie adresy URL https: //010.010.000010.010/ , https: //0x8.0x8.0x0008.0x8/ , https: //8.8.2056/ , https: //8.526344/ , https: // 134744072 / są poprawne i tylko kreatywne sposoby pisania https://8.8.8.8/ .
  • Zezwalanie na adresy zwrotne ( http://127.0.0.1/ ), prywatne adresy IP ( http://192.168.1.1 ), adresy lokalne dla linków ( http://169.254.100.200 ) i tak dalej mogą mieć wpływ na bezpieczeństwo lub Prywatność. Jeśli, na przykład, zezwalasz im na adres awatarów użytkowników na forum, powodujesz, że przeglądarki użytkowników wysyłają niezamówione żądania sieciowe w sieci lokalnej i w Internecie rzeczy, które mogą powodować śmieszne i niezbyt śmieszne rzeczy zdarzyć się w twoim domu.
  • Z tych samych powodów możesz odrzucić linki do niekompletnych nazw hostów, innymi słowy nazwy hostów bez kropki.
  • Ale nazwy hostów mogą zawsze mieć kropkę (jak w http://www.stackoverflow.com.).
  • Część nazwy hosta łącza może zawierać nawiasy kątowe dla adresów IPv6, jak w http: // [:: 1] .
  • Adresy IPv6 mają również zakresy dla sieci prywatnych lub adresów lokalnych dla łącza itp.
  • Jeśli blokujesz niektóre adresy IPv4, pamiętaj, że na przykład https://127.0.0.1 i https: // [:: ffff: 127.0.0.1] wskazują na ten sam zasób (jeśli urządzenie sprzężenia zwrotnego komputera jest gotowe na IPv6 ).
  • Część adresu URL dotycząca nazwy hosta może teraz zawierać Unicode, więc zakres znaków na [-0-9a-zA-z]pewno nie jest już wystarczający.
  • Wiele rejestrów dla domen najwyższego poziomu określa określone ograniczenia, na przykład dotyczące dozwolonego zestawu znaków Unicode. Lub dzielą przestrzeń nazw (podobnie jak co.uki wiele innych).
  • Domeny najwyższego poziomu nie mogą zawierać cyfr dziesiętnych, a łącznik nie jest dozwolony, chyba że dla prefiksu etykiety A IDN „xn--”.
  • Domeny najwyższego poziomu w Unicode (i ich kodowanie paskowe za pomocą „xn--”) muszą nadal zawierać tylko litery, ale kto chce to sprawdzić w wyrażeniu regularnym?

Które z tych ograniczeń i zasad mają zastosowanie, jest kwestią wymagań i gustu projektu.

Niedawno napisałem walidator URL dla aplikacji internetowej, która jest odpowiednia dla adresów URL dostarczanych przez użytkowników na forach, sieciach społecznościowych i tym podobnych. Możesz go używać jako podstawy własnego:

Napisałem również wpis na blogu The Gory Details of URL Validation z bardziej szczegółowymi informacjami.


1

Zmieniam funkcję na Dopasuj + dokonuję tutaj zmiany za pomocą ukośników i jej działania: (http: // i https) oba

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

Oto tylko bardzo prosta kontrola, aby upewnić się, że istnieje prawidłowy protokół, a rozszerzenie domeny musi składać się z dwóch lub więcej znaków.

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

Jeśli potrzebujesz także obsługiwać, https://localhost:3000użyj tej zmodyfikowanej wersji wyrażenia regularnego [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

Istnieje kilka testów z użyciem konstruktora URL, które nie określają, czy dane wejściowe są ciągiem czy obiektem 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

Aktualizacja 2020. Aby rozwinąć zarówno doskonałą odpowiedź z @iamnewton i @Fernando Chavez Herrera, zacząłem widzieć, @że są używane na ścieżce adresów URL.

Zaktualizowany wyrażenie regularne to:

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

Jeśli chcesz zezwolić na to w ciągu zapytania i skrócie, użyj:

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

Biorąc to pod uwagę, nie jestem pewien, czy @w łańcuchu zapytania lub haszu istnieje reguła białej księgi.


0

Jest już wiele odpowiedzi, ale oto kolejny wkład: zaczerpnięty bezpośrednio z URLkontroli poprawności wypełniania, użyj inputelementu, type="url"aby skorzystać z wbudowanej kontroli poprawności przeglądarki:

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

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

Źródło

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.