Comment puis-je tester une URL s'il s'agit d'un chemin relatif ou absolu en Javascript ou jQuery? Je veux gérer en conséquence selon que l'URL transmise est un chemin local ou externe.
if (urlString starts with http:// or https://)
//do this
var pat = /^https?:\/\//i;
if (pat.test(urlString))
{
//do stuff
}
Pour les URL relatives au protocole, utilisez cette expression régulière:
/^https?:\/\/|^\/\//i
Si vous avez seulement besoin de tester http://
ou https://
alors la façon la plus efficace est:
if (urlString.indexOf('http://') === 0 || urlString.indexOf('https://') === 0)
Cependant, je suggérerais une approche plus universelle, non sensible à la casse, agnostique au protocole:
var r = new RegExp('^(?:[a-z]+:)?//', 'i');
r.test('http://example.com'); // true - regular http absolute URL
r.test('HTTP://EXAMPLE.COM'); // true - HTTP upper-case absolute URL
r.test('https://www.exmaple.com'); // true - secure http absolute URL
r.test('ftp://example.com/file.txt'); // true - file transfer absolute URL
r.test('//cdn.example.com/lib.js'); // true - protocol-relative absolute URL
r.test('/myfolder/test.txt'); // false - relative URL
r.test('test'); // false - also relative URL
^(?:[a-z]+:)?//
^
- début de la chaîne(?:
- début d'un groupe non capturé[a-z]+
- tout caractère de 'a' à 'z' 1 fois ou plus:
- chaîne (caractère deux-points))?
- fin du groupe non capturé. Groupe apparaissant 0 ou 1 fois//
- chaîne (deux caractères de barre oblique)'i'
- indicateur non sensible à la casse
Utilisez une expression régulière:
if (/^(?:[a-z]+:)?\/\//i.test(url))
Un contrôle très très rapide et très flexible est:
if (url.indexOf('://') > 0 || url.indexOf('//') === 0 ) {
// URL is absolute; either "http://example.com" or "//example.com"
} else {
// URL is relative
}
Cela reconnaîtra une URL absolue, si:
Voici une fonction rapide qui retourne vrai/faux pour l'URL donnée:
function isUrlAbsolute(url) {
return (url.indexOf('://') > 0 || url.indexOf('//') === 0);
}
Et même dans ES6:
const isUrlAbsolute = (url) => (url.indexOf('://') > 0 || url.indexOf('//') === 0)
Pour adresser en outre des URL au format /redirect?target=http://example.org
Je recommande d'utiliser ce code:
function isUrlAbsolute(url) {
if (url.indexOf('//') === 0) {return true;} // URL is protocol-relative (= absolute)
if (url.indexOf('://') === -1) {return false;} // URL has no protocol (= relative)
if (url.indexOf('.') === -1) {return false;} // URL does not contain a dot, i.e. no TLD (= relative, possibly REST)
if (url.indexOf('/') === -1) {return false;} // URL does not contain a single slash (= relative)
if (url.indexOf(':') > url.indexOf('/')) {return false;} // The first colon comes after the first slash (= relative)
if (url.indexOf('://') < url.indexOf('.')) {return true;} // Protocol is defined before first dot (= absolute)
return false; // Anything else must be relative
}
Et la même chose sous forme abrégée et ES 6
// Traditional JS, shortened
function isUrlAbsolute(url) {
return url.indexOf('//') === 0 ? true : url.indexOf('://') === -1 ? false : url.indexOf('.') === -1 ? false : url.indexOf('/') === -1 ? false : url.indexOf(':') > url.indexOf('/') ? false : url.indexOf('://') < url.indexOf('.') ? true : false;
}
// ES 6
const isUrlAbsolute = (url) => (url.indexOf('//') === 0 ? true : url.indexOf('://') === -1 ? false : url.indexOf('.') === -1 ? false : url.indexOf('/') === -1 ? false : url.indexOf(':') > url.indexOf('/') ? false : url.indexOf('://') < url.indexOf('.') ? true : false)
Voici quelques cas de test:
// Test
console.log( isUrlAbsolute('http://stackoverflow.com') ) // -> true
console.log( isUrlAbsolute('//stackoverflow.com') ) // -> true
console.log( isUrlAbsolute('stackoverflow.com') ) // -> false
console.log( isUrlAbsolute('Ftp://example.net') ) // -> true
console.log( isUrlAbsolute('/redirect?target=http://example.org') ) // -> false
J'ai vu quelques commentaires sur une sortie non valide:
localhost
http:example.com
Cependant, ces URL sont en effet des URL relatives . C'est facile à tester:
- Créez des dossiers sur votre racine locale d'hôte, dites
a/b/c/
- Créez un fichier index.html et placez-y le lien suivant:
<a href="localhost">test</a>
- Ouvrez la page d'index dans votre navigateur: http: //localhost/a/b/c/index.html et cliquez sur le lien. Vous terminerez sur http: // localhost/a/b/c/localhost (et non sur http: // localhost )
- La même chose se produit lors du placement du lien
http:example.com
dans votre fichier index.html. Vous vous retrouvez sur http: //localhost/a/b/c/example.com au lieu de http://example.com
De nos jours, lorsque de nombreux services utilisent RL relative au protocole (par exemple // cdn.example.com/libary.js), cette méthode est plus sûre:
var isAbsolute = new RegExp('^([a-z]+://|//)', 'i');
if (isAbsolute.test(urlString)) {
// go crazy here
}
(?:^[a-z][a-z0-9+.-]*:|\/\/)
explication regex
Les autres solutions répertoriées ici échoueraient pour des liens comme mailto:[email protected]
La RFC 3986 définit un schéma comme:
scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
3.1. Schéma https://tools.ietf.org/html/rfc3986#section-3.1
Bien que l'URL relative au protocole soit techniquement valide conformément à la section 4.2, Paul Irish a fait marche arrière et considère qu'il s'agit d'un anti-modèle. Voir http://www.paulirish.com/2010/the-protocol-relative-url/
4.2. Référence relative http://tools.ietf.org/html/rfc3986#section-4.2
Si vous souhaitez utiliser l'expression régulière sans utiliser d'URL relative au protocole:
^[a-z][a-z0-9+.-]*:
Pour voir une liste complète d'autres types de valises uri Edge valides, consultez la liste ici: https://en.wikipedia.org/wiki/URI_scheme
N'utilisez pas de trucs de bas niveau comme regexp etc. Ces choses ont été résolues par tant d'autres personnes. Surtout les cas Edge.
Jetez un œil à RI.js , il devrait faire le travail: http://medialize.github.io/URI.js/docs.html#is
var uri = new URI("http://example.org/");
uri.is("absolute") === true;
var external = RegExp('^(https?:)?//');
if(external.test(el)){
// do something
}
MODIFIER:
Avec l'expression régulière suivante, vous pouvez même vérifier si le lien va vers le même domaine ou vers un domaine externe:
var external = RegExp('^((f|ht)tps?:)?//(?!' + location.Host + ')');
if(external.test(el)){
// do something
}
Selon vos besoins, je pense qu'un moyen plus fiable de le déterminer est d'utiliser interface URL intégrée pour construire quelques objets URL et comparer les origines.
new URL(document.baseURI).Origin === new URL(urlToTest, document.baseURI).Origin;
Cela permet au navigateur d'analyser et de comprendre tout cela pour vous, sans avoir à vous soucier des effets secondaires des coques Edge.
La fonction suivante sera appelée lorsqu'un clic se produit même sur un lien hypertexte, c'est-à-dire une balise 'a' si la balise contient une URL sera relative ou contient le même hôte, alors cette nouvelle page sera chargée dans le même onglet du navigateur si elle contient une URL différente, la page se chargera nouvel onglet du navigateur
jQuery(document).ready(function() {
$('a').click(function(){
var a = this;
var a_href = $(this).attr('href');
var regex = new RegExp('^(?:[a-z]+:)?//', 'i');
if(a.Host == location.Host || regex.test(a_href) == false){
a.target = '_self';
}else{
a.target = '_blank';
}
});
});
var adress = 'http://roflmao.com';
if (adress.substr(0,7) == 'http://' || adress.substr(0,8) == 'https://') {
//
}
Voici une approche à toute épreuve du problème:
Laissez le navigateur gérer tout pour nous. Pas besoin de regex compliqué/sujet aux erreurs.
const isAbsoluteUrl = (url) => {
const link = document.createElement('a');
link.href = url;
return link.Origin + link.pathname + link.search + link.hash === url;
};
Malheureusement, ne fonctionne pas dans un environnement nodejs.