Vérifiez si une chaîne JavaScript est une URL

284

Existe-t-il un moyen en JavaScript pour vérifier si une chaîne est une URL?

Les RegExes sont exclus car l'URL est très probablement écrite comme stackoverflow; c'est - à - dire qu'il pourrait ne pas avoir .com, wwwou http.

Bruno
la source
22
S'il manque le http, c'est par défaut pas d'url.
nfechner
1
@nfechner, c'est-à-dire que s'il ne spécifie pas de protocole et utilise le caractère deux-points (de préférence avec deux barres obliques à côté), ce n'est pas une URL?
jcolebrand le
5
Comme vous pouvez le lire dans l' URL RFC , la seule partie réellement nécessaire pour faire d'une chaîne une URL valide est le deux-points. Les URL valides ressemblent à:<scheme>:<scheme-specific-part>
nfechner
8
La façon dont vous testez si quelque chose est une URL est très dépendante du contexte et trop vague sans autre qualification. Est-il important pour vous qu'il soit conforme à la spécification URL RFC, fonctionne lors d' un appel système OS pour ouvrir l'URL , analyse comme un hrefélément d'ancrage, fonctionne lors de l'appel window.open(url), pointe vers quelque chose qui existe vraiment, fonctionne à l'emplacement du navigateur ou une combinaison des éléments ci-dessus? Vous obtiendrez des réponses très différentes en fonction de celles qui vous intéressent.
Roy Tinker

Réponses:

189

Une question connexe avec une réponse:

Correspondance URL regex Javascript

Ou ce Regexp de 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);
}
Tom Gullen
la source
1
Je sais mais je cherche dans mes favoris et la plupart d'entre eux sont écrits comme stackoverflow (sans .com, etc.)
Bruno
4
@Bruno: il est très probable qu'ils soient enregistrés en interne avec des titres et des URL séparés, comme { title: "Stackoverflow", uri: "http://stackoverflow.com" } Update: en effet, voir code.google.com/chrome/extensions/bookmarks.html
Marcel Korpel
10
essayer d'utiliser votre exemple. Mais je reçois une erreur sur firebug qui dit invalid quantifier. Une idée?
Sisir
125
Retours de fonctions: 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 (Version 30.0.1599.101) (Mac OS X: 10.8.5)
dr.dimitru
10
Sachez que si vous utilisez une chaîne comme paramètre pour le, RegExpvous devez double échapper les barres obliques inverses - sinon vous obtenez des erreurs comme un groupe non valide .
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);
}
Zemljoradnik
la source
13
échoue pour les liens d'image de recherche 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
bill davis
7
c'est inutilisable lent
Hernán Eche
3
@ HernánEche Que voulez-vous dire par lent ? start = new Date(); isURL("http://michalstefanow.com"); end = new Date(); diff = end - start; console.log(diff)J'ai mis une bouilloire, je suis allé aux toilettes, j'ai appelé ma mère et la chose a été faite en un rien de temps ...
Mars Robertson
62
Il revient truepour aaa.
alex naumov
1
Cela ne devrait absolument pas être la bonne réponse. Il échoue à de nombreux cas de test et, plus important encore, il bloque votre page sur une chaîne même courte: isURL('12345678901234567890123')ajoutez quelques caractères supplémentaires et c'est encore pire.
aamarks
142

Vous pouvez essayer d'utiliser le URLconstructeur : s'il ne lance pas, la chaîne est une URL valide:

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

  return true;
}

Le terme «URL» est défini dans la RFC 3886 (comme URI); il doit commencer par un nom de schéma et le nom du schéma n'est pas limité à http / https.

Exemples notables:

  • www.google.com n'est pas une URL valide (schéma manquant)
  • javascript:void(0) est une URL valide, mais pas HTTP
  • http://..est une URL valide, l'hôte étant ..; s'il résout dépend de votre DNS
  • https://google..com est une URL valide, identique à celle ci-dessus

Si vous souhaitez vérifier si une chaîne est une URL HTTP valide:

function isValidHttpUrl(string) {
  let url;

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

  return url.protocol === "http:" || url.protocol === "https:";
}
Pavlo
la source
13
@AshD non, ce n'est pas le cas; par exemple, vous ne pouvez pas utiliser comme hrefattribut pour <a>. Une URL valide doit commencer par un nom de schéma , par exemple https://.
Pavlo
3
nouvelle URL ('javascript: alert (23)')
blade091
6
@Pavlo, cela revient vraiisValidUrl("javascript:void(0)")
Praveena
3
J'aime ça pour m'apprendre de nouvelles choses sur js! Il n'y a pas de faux négatifs que j'ai pu trouver. Il a quelques faux positifs: http://..Ouhttp:///a
aamarks
2
L'URL fonctionne à partir d'Edge, donc tout ce qui se trouve en dessous peut ne pas fonctionner comme prévu. Assurez-vous de vérifier d'abord la compatibilité.
Tony T.
97

Plutôt que d'utiliser une expression régulière, je recommanderais d'utiliser un élément d'ancrage.

lorsque vous définissez la hrefpropriété d'un anchor, diverses autres propriétés sont définies.

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"

la source

Cependant, si la valeur hrefest liée à n'est pas une URL valide, la valeur de ces propriétés auxiliaires sera la chaîne vide.

Modifier: comme indiqué dans les commentaires: si une URL non valide est utilisée, les propriétés de l'URL actuelle peuvent être remplacées.

Donc, tant que vous ne transmettez pas l'URL de la page actuelle, vous pouvez faire quelque chose comme:

function isValidURL(str) {
   var a  = document.createElement('a');
   a.href = str;
   return (a.host && a.host != window.location.host);
}
Luc
la source
3
Ce n'est pas le cas (dans Chrome 48 au moins). Si l'URL transmise à a.hrefn'est pas valide, parser.hostrenvoie le nom d'hôte de la page sur laquelle vous vous trouvez actuellement, pas celui attendu false.
Sam Beckham
2
Gah! c'est bizarre. Je jure que j'ai testé ça! Je pense qu'il est juste de dire que cela ne devra jamais être utilisé sur la page actuelle, donc le conditionnel peut juste être changé. Je vais éditer le post.
Luke
ce n'est pas un cas d'utilisation très typique, mais cette technique ne fonctionne pas dans le contexte de la fenêtre du navigateur Firefox (important pour le développement de l'addon)
chrmod
@SamBeckham C'est certainement une préoccupation lors de l'utilisation de cette méthode, mais je veux juste souligner que ce n'est pas un comportement spécial. Si vous avez un lien sur votre page qui est invalide, comme <a href="invalidurl">, il n'aller à votre domaine. Il est ajouté à la fin de l'URL actuelle. Chrome fait donc ce qu'il faut en vous donnant le nom d'hôte actuel de l'élément "parser".
yts
4
function isValidURL(str): tellement mieux que d'utiliser regex! Je vous remercie!
Rodrigo
47

J'utilise la fonction ci-dessous pour valider l'URL avec ou sans 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

Vikasdeep Singh
la source
2
Semble une bonne solution! Pourriez-vous ajouter des tests montrant que cela fonctionne dans certains cas d'angle (voir par exemple ces commentaires )?
Basj
@Basj a ajouté des cas de test. Veuillez vérifier
Vikasdeep Singh
Pas mal, ne parvient pas à passer http: //⌘.ws ou 142.42.1.1 et il autorise http: //.www.foo.bar./ mais il ne se bloque pas comme certains des autres regex, y compris les réponses les mieux notées.
aamarks
@aamarks J'ai vérifié votre réponse. Votre réponse échoue pour le https://sdfasdp.pppppppppppretour, truemais la mienne revient, falsece qui est attendu, je pense.
Vikasdeep Singh
4
son retour vrai pour [email protected]... devrait-il? Je suppose que ça ne devrait pas
Zohab Ali
35

Pour valider l'URL à l'aide de javascript est indiqué ci-dessous

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;
  }
}
kavitha Reddy
la source
3
Plusieurs parties de l'expression régulière pourraient être considérablement réduites: a) (http|https)à (?:https?); b) :{0,1}à :?; c) [0-9]à\d
Dmitry Parzhitsky
28

Comptez sur une bibliothèque: https://www.npmjs.com/package/valid-url

import { isWebUri } from 'valid-url';
// ...
if (!isWebUri(url)) {
    return "Not a valid url.";
}
Michael Bushe
la source
celui-ci me donne beaucoup de mal avec les URL étranges qui sont en fait analysées par le navigateur, par exemple: avoir un {dans l'URL
Willyfrog
23

Amélioration de la réponse acceptée ...

  • Vérifiez ftp / ftps comme protocole
  • A un double échappement pour les contre-obliques (\\)
  • Garantit que les domaines ont un point et une extension (.com .io .xyz)
  • Autorise les deux-points (:) dans le chemin, par exemple http://thingiverse.com/download:1894343
  • Permet l'esperluette (&) dans le chemin, par exemple http://en.wikipedia.org/wiki/Procter_&_Gamble
  • Permet le symbole @ dans le chemin, par exemple 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);
    }
Mwirabua Tim
la source
5
Non, cela ne devrait pas être la réponse acceptée. Comme certains autres, il se bloque sur une simple chaîne de 33 caractères: isURL ('123456789012345678901234567890123') et échoue à de nombreux tests de cas de bord: foo.com/blah_blah_(wikipedia)_(again) // renvoie incorrectement false.
aamarks
2
C'est parce que localhost: 8080 n'est pas une URL valide.
Shane
1
Exemple de
Shane
Doit être ftps: // localhost: 8080 =)
vp_arth
Cela ne semble pas fonctionner: se bloque sur une entrée longue (comme l'a dit @aanmarks)
cecemel
13

Voici encore une autre méthode.

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

Ryan Breece
la source
Code éducatif! Le mécanisme ici est probablement identique à la façon dont fonctionne new URL(string)le code de Pavlo. Les deux tests ont des résultats identiques avec tous les cas de bord que j'ai testés. J'aime son code car il est plus simple et n'implique pas de créer des éléments, mais le vôtre est quelques fois plus rapide (probablement parce qu'il ne crée pas l'el après la première utilisation).
aamarks
1
Je vous remercie! J'ai mis en œuvre vos conseils. Attention toutefois: les anciens navigateurs et / ou appareils mobiles WebView n'ont peut-être pas implémenté l'élément <input type = url>; ainsi la valeur d'entrée serait traitée comme un texte normal (pas de validation d'URL). REF: developer.mozilla.org/en-US/docs/Web/HTML/Element/input/url
Panini Luncher
10

(Je n'ai pas de représentants pour commenter l' exemple de ValidURL ; par conséquent, postez ceci comme réponse.)

Bien que l'utilisation d'URL relatives au protocole ne soit pas encouragée (l' URL relative au protocole ), elles sont parfois utilisées. Pour valider une telle URL avec une expression régulière, la partie protocole peut être facultative, par exemple:

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

Comme d'autres l'ont fait remarquer, l'expression régulière ne semble cependant pas être l'approche la mieux adaptée pour valider les URL.

ko la
la source
Au début, je pensais que c'était plutôt bien, mais cela échoue à de nombreux tests sur mathiasbynens.be/demo/url-regex , puis ça tientisValidURL("https://[email protected]/13176")
aamarks
Oui, comme je l'ai dit, j'ai simplement commenté la partie protocole. J'ai ajouté la clause d'authentification à gérer @. Il ne se bloque pas dans mes navigateurs .
ko la
Désolé, je passais en revue plusieurs de ces derniers pour les évaluer et j'ai manqué que le vôtre commente la réponse donnée. Je pense que votre correction m'a même aidé à démarrer sur ces derniers lorsque j'ai visité cette page pour la première fois. Ne pend pas maintenant.
aamarks
9

Vous pouvez utiliser l' API native URL :

  const isUrl = string => {
      try { return Boolean(new URL(string)); }
      catch(e){ return false; }
  }
Aral Roca
la source
3
Cela ressemble beaucoup à la réponse fournie par @pavlo, seuls les noms de variables ont changé;)
Munim Munna
2
il devrait vraiment y avoir une méthode native simple pour vérifier cela maintenant - cette réponse avait l'air très prometteuse mais elle est vraie dès que @Basj l'a mentionné ci-dessus.
zero_cool
8

Comme cela a été noté, l'expression rationnelle parfaite est insaisissable mais semble toujours être une approche raisonnable (les alternatives sont les tests côté serveur ou la nouvelle API URL expérimentale ). Cependant, les réponses de haut niveau retournent souvent false pour les URL courantes, mais pire encore, votre application / page se fige pendant des minutes, même sur une chaîne aussi simple que isURL('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'). Il a été souligné dans certains commentaires, mais n'a probablement pas entré une mauvaise valeur pour le voir. Suspendre comme ça rend ce code inutilisable dans toute application sérieuse. Je pense que c'est dû aux jeux répétés insensibles à la casse dans le code comme ((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.?)+[a-z]{2,}|' .... Retirez le «i» et il ne se bloque pas mais ne fonctionnera bien sûr pas comme vous le souhaitez. Mais même avec l'indicateur ignore case, ces tests rejettent les valeurs unicode élevées qui sont autorisées.

Le meilleur déjà mentionné est:

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

Cela vient de Github segmentio / is-url . La bonne chose à propos d'un référentiel de code est que vous pouvez voir les tests et tous les problèmes ainsi que les chaînes de test qui les parcourent. Il y a une branche qui permettrait aux chaînes de protocole manquantes google.com, bien que vous fassiez probablement trop d'hypothèses à ce moment-là. Le référentiel a été mis à jour et je n'ai pas l'intention d'essayer de garder un miroir ici. Il a été divisé en tests séparés pour éviter les redos RegEx qui peuvent être exploités pour les attaques DOS (je ne pense pas que vous ayez à vous en soucier avec js côté client, mais vous devez vous soucier de la suspension de votre page pendant si longtemps que votre visiteur quitte votre site).

Il y a un autre référentiel que j'ai vu qui pourrait même être meilleur pour isURL sur dperini / regex-weburl.js , mais il est très complexe. Il a une plus grande liste de tests d'URL valides et invalides. Le simple ci-dessus passe toujours tous les points positifs et ne parvient à bloquer que quelques négatifs impairs, http://a.b--c.de/ainsi que les ips spéciaux.

Quel que soit votre choix, exécutez-la via cette fonction que j'ai adaptée des tests sur dperini / regex-weburl.js, tout en utilisant l'inspecteur des outils de développement de votre navigateur.

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

Et puis testez cette chaîne de «a».

Voir cette comparaison des expressions régulières isURL par Mathias Bynens pour plus d'informations avant de publier une expression régulière apparemment géniale.

aamarks
la source
J'ai vérifié ta réponse. Votre réponse échoue pour sdfasdp.ppppppppppp c'est-à-dire renvoyer vrai mais attendu est faux
Vikasdeep Singh
1
Je pense que c'est une URL valide, structurellement. Pas un expert de la norme mais je ne pense pas qu'il y ait une limite à la longueur de la portion .com (je sais que .online est légitime).
aamarks
1
Je savais à peine comment écrire une expression régulière il y a quelques mois. Le problème est grave. Les deux expressions rationnelles que j'ai citées peuvent se terminer des isURL('a'.repeat(100))millions de fois / s (la plus complexe de dperini est en fait plus rapide). Certaines des réponses de haut niveau du formulaire ([a-zA-Z] +) * prendraient des heures pour le remplir une fois. Recherchez les fichiers RegEx pour plus d'informations.
aamarks
6

Je ne peux pas commenter le message le plus proche # 5717133 , mais ci-dessous est la façon dont j'ai compris comment faire fonctionner @ 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
la source
2
Cela a fonctionné pour moi, mais je devais annuler les contre-obliques. 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
Consultez w3resource.com/javascript-exercises/… pour plus de cas de test
Kewal Shah
5

Utilisez validator.js

ES6

import isURL from 'validator/lib/isURL'

isURL(string)

Non ES6

var validator = require('validator');

validator.isURL(string)

Vous pouvez également affiner le comportement de cette fonction en passant un optionsobjet facultatif comme deuxième argument deisURL

Voici l' optionsobjet par défaut :

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_whitelistet host_blacklistpeuvent être des tableaux d'hôtes. Ils prennent également en charge les expressions régulières.

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
Ilyich
la source
1
Agréable! Petite bibliothèque (moins de 40 000 minifiés), bibliothèque populaire (plus de 3 millions de téléchargements hebdomadaires sur npm), vous offre des tonnes de flexibilité pour spécifier la validité des URL pour votre cas d'utilisation particulier, et dispose d'un certain nombre d'autres validateurs en plus de l'URL. C'est de loin la meilleure réponse, à mon humble avis.
Javid Jamae
4

Une fonction que j'ai utilisée pour valider une "chaîne" d'URL est:

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

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

Cette fonction retournera un booléen si la chaîne est une URL.

Exemples:

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
Chris
la source
4

C'est assez difficile à faire avec une expression rationnelle pure, car les URL présentent de nombreux «inconvénients».

  1. Par exemple, les noms de domaine ont des restrictions compliquées sur les tirets:

    une. Il est permis d'avoir plusieurs traits d'union consécutifs au milieu.

    b. mais le premier caractère et le dernier caractère du nom de domaine ne peuvent pas être un trait d'union

    c. Les 3e et 4e caractères ne peuvent pas être à la fois un trait d'union

  2. De même, le numéro de port ne peut être compris que dans la plage 1-65535. Ceci est facile à vérifier si vous extrayez la partie du port et la convertissez en intmais assez difficile à vérifier avec une expression régulière.

  3. Il n'existe également aucun moyen simple de vérifier les extensions de domaine valides. Certains pays ont des domaines de second niveau (tels que «co.uk»), ou l'extension peut être un mot long comme «.international». Et de nouveaux TLD sont ajoutés régulièrement. Ce type de choses ne peut être vérifié que par rapport à une liste codée en dur. (voir https://en.wikipedia.org/wiki/Top-level_domain )

  4. Ensuite, il y a les URL des aimants, les adresses ftp, etc. Elles ont toutes des exigences différentes.

Néanmoins, voici une fonction qui gère à peu près tout sauf:

  • Cas 1. c
  • Accepte tout numéro de port de 1 à 5 chiffres
  • Accepte toute extension 2-13 caractères
  • N'accepte pas ftp, aimant, etc ...

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] + ']');
}

Caner
la source
1

Je pense que l'utilisation de l' API URL native est meilleure qu'un modèle d'expression régulière complexe comme l'a suggéré @pavlo. Il présente cependant certains inconvénients que nous pouvons corriger par du code supplémentaire. Cette approche échoue pour l'URL valide suivante.

//cdn.google.com/script.js

Nous pouvons ajouter le protocole manquant au préalable pour éviter cela. Il ne parvient pas non plus à détecter les URL non valides suivantes.

http://w
http://..

Alors pourquoi vérifier l'url entière? nous pouvons simplement vérifier le domaine. J'ai emprunté l'expression régulière pour vérifier le domaine d' ici .

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

L' hostnameattribut est une chaîne vide pour javascript:void(0), il fonctionne donc aussi, et vous pouvez également ajouter un vérificateur d'adresse IP. Je voudrais m'en tenir à la plupart des API natives et j'espère qu'elles commenceront à tout prendre en charge dans un avenir proche.

Munim Munna
la source
Intéressant, mais peut-être encore besoin de travailler sur l'expression régulière car il a maintenant introduit de faux négatifs qui new URLne figurent pas dans les tests que j'ai effectués. Cela appelle: http://142.42.1.1 //falseet bloque les chaînes Unicode élevées.
aamarks
1

La question demande une méthode de validation pour une URL telle que stackoverflow , sans le protocole ou aucun point dans le nom d'hôte. Il ne s'agit donc pas de valider la sintax de l'url, mais de vérifier si c'est une url valide, en l'appelant.

J'ai essayé plusieurs méthodes pour savoir si l'URL true existe et peut être appelée à partir du navigateur, mais je n'ai trouvé aucun moyen de tester avec javascript l'en-tête de réponse de l'appel:

  • l'ajout d'un élément d'ancrage est très bien pour lancer la click()méthode.
  • faire un appel ajax à l'url difficile avec 'GET'est très bien, mais a ses diverses limitations en raison deCORS politiques et ce n'est pas le cas de l'utilisationajax , car comme l'url peut-être toute en dehors du domaine de mon serveur.
  • en utilisant le API fetch a une solution de contournement similaire à ajax.
  • un autre problème est que j'ai mon serveur sous https protocole et lève une exception lors de l'appel des URL non sécurisées.

Donc, la meilleure solution à laquelle je peux penser est d'obtenir un outil à CURLutiliser en utilisant javascript en essayant quelque chose comme curl -I <url>. Malheureusement je n'en ai pas trouvé et en apparence ce n'est pas possible. J'apprécierai tout commentaire à ce sujet.

Mais au final, j'ai un serveur qui tourne PHP et comme j'utilise Ajax pour presque toutes mes demandes, j'ai écrit une fonction côté serveur pour y exécuter la demande curl et revenir au navigateur.

En ce qui concerne l'URL d'un seul mot sur la question «stackoverflow», cela https://daniserver.com.ar/stackoverflowm'amènera à , où daniserver.com.ar est mon propre domaine.

Daniel Faure
la source
Le PO aurait probablement dû indiquer davantage son intention. Le problème varie certainement selon vos besoins et s'il est plus important d'exclure les faux positifs ou d'inclure les faux négatifs. Comme le problème est énoncé, il ne semble pas y avoir de réponse pour moi. Pouvez-vous vraiment prendre fooet supposer que c'est http ou https ou .com ou .es ou l'un des innombrables suffixes? Continuez-vous à jeter l'évier de cuisine jusqu'à ce que vous obteniez un vrai?
aamarks
1

Cela semble être l'un des problèmes les plus difficiles de CS;)

Voici une autre solution incomplète qui fonctionne assez bien pour moi et meilleure que les autres que j'ai vues ici. J'utilise une entrée [type = url] pour cela afin de prendre en charge IE11, sinon il serait beaucoup plus simple d'utiliser window.URL pour effectuer la validation à la place:

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

Afin d'accepter des entrées incomplètes telles que "www.mydomain.com", il sera également valide en supposant que le protocole est "http" dans ces cas et en renvoyant l'URL valide si l'adresse est valide. Elle retourne false lorsqu'elle n'est pas valide.

Il prend également en charge les domaines IPv4, mais pas IPv6.

Rosenfeld
la source
1

Dans mon cas, ma seule exigence est que l'entrée utilisateur ne soit pas interprétée comme un lien relatif lorsqu'elle est placée dans le href d'une balise a et les réponses ici étaient soit un peu OTT pour cela, soit des URL autorisées ne répondant pas à mes exigences, donc cela c'est ce que je veux dire:

^https?://.+$

La même chose pourrait être réalisée assez facilement sans regex.

rdans
la source
1

ce travail avec moi

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
la source
1
Cette réponse a déjà été donnée il y a plus de 4 ans par kavitha Reddy.
aamarks
je viens de le rendre plus simple et abstrait
HeshamSalama
1

Si vous pouvez changer le type d'entrée, je pense que cette solution serait beaucoup plus simple:

Vous pouvez une utilisation simple type="url"dans votre entrée et la vérifier aveccheckValidity() en js

Par exemple:

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
    }
});
Daniel Rodríguez
la source
1

Ce n'est certainement pas l'approche la plus efficace, mais elle est lisible et facile à mettre en forme pour tout ce dont vous avez besoin. Et il est plus facile d'ajouter regex / complexité à partir d'ici. Voici donc une approche très pragmatique

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

TESTER:

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

la source
1

Mathias Bynens a compilé une liste de regex URL bien connus avec des URL de test. Il y a peu de raisons d'écrire une nouvelle expression régulière; choisissez simplement celui qui vous convient le mieux.

Mais le tableau de comparaison de ces expressions régulières montre également qu'il est presque impossible de faire la validation d'URL avec une seule expression régulière. Tous les regex de la liste de Bynens produisent des faux positifs et des faux négatifs.

Je vous suggère d'utiliser un analyseur d'URL existant (par exemple new URL('http://www.example.com/')en JavaScript), puis d'appliquer les vérifications que vous souhaitez effectuer par rapport à la forme analysée et normalisée de l'URL resp. ses composants. Utiliser le JavaScriptURL interface présente l'avantage supplémentaire de n'accepter que les URL réellement acceptées par le navigateur.

Vous devez également garder à l'esprit que les URL techniquement incorrectes peuvent toujours fonctionner. Par exemple http://w_w_w.example.com/, http://www..example.com/, http://123.example.com/tous ont une partie de nom d' hôte invalide mais chaque navigateur je sais vais essayer de les ouvrir sans se plaindre, et lorsque vous spécifiez les adresses IP pour les noms non valides dans /etc/hosts/ces URL vont même travailler mais seulement sur votre ordinateur.

La question n'est donc pas tant de savoir si une URL est valide, mais plutôt quelles URL fonctionnent et doivent être autorisées dans un contexte particulier.

Si vous souhaitez effectuer une validation d'URL, il existe de nombreux détails et cas marginaux faciles à ignorer:

  • Les URL peuvent contenir des informations d'identification comme dans http://user:[email protected]/.
  • Les numéros de port doivent être compris entre 0 et 65 535, mais vous souhaiterez peut-être toujours exclure le port générique 0.
  • Les numéros de port peuvent avoir des zéros en tête comme dans http://www.example.com:000080/ .
  • Les adresses IPv4 ne sont en aucun cas limitées à 4 entiers décimaux compris entre 0 et 255. Vous pouvez utiliser un à quatre entiers, et ils peuvent être décimaux, octaux ou hexadécimaux. Les URL https: //010.010.000010.010/ , https: //0x8.0x8.0x0008.0x8/ , https: //8.8.2056/ , https: //8.526344/ , https: // 134744072 / sont toutes valides et juste des façons créatives d'écrire https://8.8.8.8/ .
  • Autoriser les adresses de bouclage ( http://127.0.0.1/ ), les adresses IP privées ( http://192.168.1.1 ), les adresses de liaison locale ( http://169.254.100.200 ) et ainsi de suite peuvent avoir un impact sur la sécurité ou intimité. Si, par exemple, vous les autorisez comme adresse des avatars des utilisateurs dans un forum, vous amenez les navigateurs des utilisateurs à envoyer des demandes réseau non sollicitées dans leur réseau local et sur Internet des objets, de telles demandes peuvent provoquer des choses drôles et pas si drôles à arriver dans votre maison.
  • Pour les mêmes raisons, vous souhaiterez peut-être supprimer les liens vers des noms d'hôte non qualifiés, c'est-à-dire des noms d'hôte sans point.
  • Mais les noms d'hôtes peuvent toujours avoir un point de fin (comme dans http://www.stackoverflow.com.).
  • La partie du nom d'hôte d'un lien peut contenir des crochets pour les adresses IPv6 comme dans http: // [:: 1] .
  • Les adresses IPv6 ont également des plages pour les réseaux privés ou les adresses de liaison locale, etc.
  • Si vous bloquez certaines adresses IPv4, gardez à l'esprit que par exemple https://127.0.0.1 et https: // [:: ffff: 127.0.0.1] pointent vers la même ressource (si le périphérique de bouclage de votre machine est compatible IPv6 ).
  • La partie du nom d'hôte des URL peut maintenant contenir Unicode, de sorte que la plage de caractères [-0-9a-zA-z]n'est définitivement plus suffisante.
  • De nombreux registres pour les domaines de niveau supérieur définissent des restrictions spécifiques, par exemple sur l'ensemble autorisé de caractères Unicode. Ou ils subdivisent leur espace de noms (comme co.uket beaucoup d'autres).
  • Les domaines de niveau supérieur ne doivent pas contenir de chiffres décimaux et le tiret n'est autorisé que pour le préfixe d'étiquette A IDN "xn--".
  • Les domaines de premier niveau Unicode (et leur codage punycode avec "xn--") doivent toujours contenir uniquement des lettres, mais qui veut vérifier cela dans une expression régulière?

Laquelle de ces limitations et règles s'applique est une question d'exigences et de goût du projet.

J'ai récemment écrit un validateur d'URL pour une application Web qui convient aux URL fournies par les utilisateurs dans les forums, les réseaux sociaux ou similaires. N'hésitez pas à l'utiliser comme base pour la vôtre:

J'ai également écrit un article de blog The Gory Details of URL Validation avec des informations plus détaillées.

Guido Flohr
la source
1

Je change la fonction en Match + fais un changement ici avec les barres obliques et son travail: (http: // et https) les deux

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;
}
Ashish Gupta
la source
0

Voici juste une vérification très simple pour vous assurer qu'il existe un protocole valide, et l'extension de domaine doit être de deux caractères ou plus.

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

};
Michael Ecklund
la source
0

Si vous devez également prendre en charge, https://localhost:3000utilisez cette version modifiée de l'expression régulière de [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);
    }
Mark Hetherington
la source
0

Il existe quelques tests utilisant le constructeur d'URL qui ne déterminent pas si l'entrée est une chaîne ou un objet 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
la source
0

Mise à jour 2020. Pour développer à la fois l'excellente réponse de @iamnewton et @Fernando Chavez Herrera, j'ai commencé à voir @être utilisé dans le chemin des URL.

Donc, l'expression régulière mise à jour est:

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

Si vous souhaitez l'autoriser dans la chaîne de requête et le hachage, utilisez:

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

Cela étant dit, je ne sais pas s'il existe une règle de livre blanc interdisant @la chaîne de requête ou le hachage.

Janus
la source
0

Il y a déjà beaucoup de réponses, mais voici une autre contribution: Tiré directement du URLcontrôle de validité du polyfill, utilisez un inputélément avec type="url"pour profiter du contrôle de validité intégré du navigateur:

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

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

La source

Bruno Finger
la source