Verifique se uma string JavaScript é um URL


283

Existe uma maneira no JavaScript para verificar se uma string é um URL?

RegExes são excluídos porque o URL provavelmente é escrito como stackoverflow; isto é, pode não ter um .com, wwwou http.


22
Se estiver faltando o http, é por padrão sem URL.
Nfechner

1
@ nfechner, isto é, se ele não especificar um protocolo e usar o caractere de dois pontos (de preferência com duas barras a seguir), então não é um URL?
precisa saber é o seguinte

5
Como você pode ler na URL RFC , a única parte realmente necessária para tornar uma String uma URL válida é os dois pontos. Os URLs válidos têm a seguinte aparência:<scheme>:<scheme-specific-part>
nfechner 19/04/11


8
Como você testa se algo é um URL é altamente dependente do contexto e muito vago sem qualificação adicional. Importa a você se está em conformidade com a especificação RFC da URL, funciona ao fazer uma chamada do sistema OS para abrir a URL , analisa como um hrefelemento âncora, funciona ao chamar window.open(url), aponta para algo que realmente existe, funciona no local do navegador bar ou uma combinação dos itens acima? Você receberá respostas muito diferentes, dependendo de qual delas você gosta.
Roy Tinker

Respostas:


189

Uma pergunta relacionada com uma resposta:

Correspondência de URL de regex Javascript

Ou este Regexp do 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
Eu sei, mas eu estou procurando em meus favoritos ea maioria deles são escritos como stackoverflow (sem .com, etc.)
de Bruno

3
@Bruno: é muito provável que eles são salvos internamente com títulos e URLs separados, como { title: "Stackoverflow", uri: "http://stackoverflow.com" } Update: de fato, ver code.google.com/chrome/extensions/bookmarks.html
Marcel Korpel

10
tentando usar o seu exemplo. Mas estou recebendo um erro no firebug que diz invalid quantifier. Qualquer ideia?
Sisir 10/07/2012

125
A função retorna: 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 (versão 30.0.1599.101) (Mac OS X: 10.8.5)
dr.dimitru

10
Lembre-se de que, se você usar uma string como parâmetro, RegExpprecisará escapar duas vezes das barras invertidas - caso contrário, obterá erros como o grupo inválido .
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
falha para links google da imagem: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
isso é inutilizável lento
Hernán Eche 28/01

3
@ HernánEche O que você quer dizer com lento ? start = new Date(); isURL("http://michalstefanow.com"); end = new Date(); diff = end - start; console.log(diff)Eu coloquei uma chaleira no fogo, foi para um banheiro, liguei para minha mãe e a coisa foi feito em nenhum momento ...
Mars Robertson

62
Retorna truepara aaa.
Alex naumov 01/12/16

1
Isso absolutamente não deve ser a resposta correta. Ele falha em muitos casos de teste e, mais importante, trava a sua página em uma sequência curta: isURL('12345678901234567890123')adicione mais caracteres e isso é ainda pior.
precisa saber é

141

Você pode tentar usar o URLconstrutor : se não lançar, a string será uma URL válida:

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

  return true;
}

O termo 'URL' é definido no RFC 3886 (como URI); ele deve começar com um nome de esquema e o nome do esquema não se limita a http / https.

Exemplos notáveis:

  • www.google.com URL inválido (esquema ausente)
  • javascript:void(0) é um URL válido, embora não seja HTTP
  • http://..é URL válida, com o anfitrião ser ..; se a resolução depende do seu DNS
  • https://google..com é um URL válido, o mesmo que acima

Se você deseja verificar se uma sequência é um URL HTTP válido:

function isValidHttpUrl(string) {
  let url;

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

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

13
@ AshD não, não é; por exemplo, você não pode usar como hrefatributo para <a>. URL válido deve começar com um nome de esquema , por exemplo https://.
Pavlo 21/04

3
novo URL ('javascript: alert (23)')
blade091

6
@Pavlo this return trueisValidUrl("javascript:void(0)")
Praveena

3
Eu gosto disso por me ensinar coisas novas sobre js! Não há falsos negativos que eu possa encontrar. Ele tem alguns falsos positivos: http://..Ouhttp:///a
aamarks

2
O URL está funcionando a partir do Edge, portanto, tudo abaixo dele pode não funcionar conforme o esperado. Certifique-se de verificar a compatibilidade primeiro.
Tony T.

97

Em vez de usar uma expressão regular, eu recomendaria fazer uso de um elemento âncora.

quando você define a hrefpropriedade de um anchor, várias outras propriedades são definidas.

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"

fonte

No entanto, se o valor hrefestiver associado a um URL inválido, o valor dessas propriedades auxiliares será a sequência vazia.

Editar: como indicado nos comentários: se um URL inválido for usado, as propriedades do URL atual poderão ser substituídas.

Portanto, contanto que você não esteja transmitindo o URL da página atual, você pode fazer algo como:

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

3
Este não é o caso (pelo menos no Chrome 48). Se o URL transmitido a.hreffor inválido, parser.hostretornará o nome do host da página em que você está atualmente, não o esperado false.
Sam Beckham

2
Gah! isso é estranho. Eu juro que testei isso! Eu acho que é justo dizer que isso realmente nunca precisará ser usado na página atual, então o condicional pode ser alterado. Eu vou editar a postagem.
25416 Luke

não é um caso de uso muito típico, mas esta técnica não funciona no contexto da janela do navegador Firefox (importante para o desenvolvimento addon)
chrmod

@ SamBeckham Essa é definitivamente uma preocupação ao usar esse método, mas eu só quero ressaltar que esse não é um comportamento especial. Se você tem um link inválido na sua página, por exemplo <a href="invalidurl">, ele é direcionado ao seu domínio. Ele é adicionado ao final do URL atual. Portanto, o Chrome está fazendo a coisa correta, fornecendo o nome do host atual do elemento "analisador".
yts 14/12/19

4
function isValidURL(str): muito melhor do que usar regex! Obrigado!
Rodrigo

46

Estou usando a função abaixo para validar URL com ou sem 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
Parece uma boa solução! Você poderia adicionar alguns testes mostrando que funciona em alguns casos de canto (veja, por exemplo, esses comentários )?
Basj

@Basj adicionou casos de teste. Por favor, verifique
Vikasdeep Singh

Nada mal, falha ao passar http: //⌘.ws ou 142.42.1.1 e permite http: //.www.foo.bar./, mas não é interrompido como alguns dos outros regex, incluindo as respostas mais votadas.
precisa saber é

@aamarks Eu verifiquei sua resposta. Sua resposta está falhando, https://sdfasdp.pppppppppppisto é, retornando, truemas a minha volta, o falseque é esperado, eu acho.
23918 Vikasdeep Singh

4
seu retorno verdadeiro para sadf@gmail.com... deveria? Eu acho que não deveria
Zohab Ali

35

Para validar o URL usando javascript é mostrado abaixo

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
Várias partes do regex podem ser amplamente reduzidas: a) (http|https)para (?:https?); b) :{0,1}para :?; c) [0-9]para\d
Dmitry Parzhitsky


23

Melhoria na resposta aceita ...

  • Verifique se há ftp / ftps como protocolo
  • Possui escape duplo para barras invertidas (\\)
  • Garante que os domínios tenham um ponto e uma extensão (.com .io .xyz)
  • Permite dois pontos (:) no caminho, por exemplo, http://thingiverse.com/download:1894343
  • Permite e comercial (&) no caminho, por exemplo, http://en.wikipedia.org/wiki/Procter_&_Gamble
  • Permite @ símbolo no caminho, por exemplo, 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
Não, não deve ser a resposta aceita. Como alguns dos outros, ele fica com uma mera sequência de 33 caracteres: isURL ('123456789012345678901234567890123') e falha em muitos testes de casos: foo.com/blah_blah_(wikipedia)_(again) // retorna incorretamente falso.
precisa saber é

2
Isso ocorre porque localhost: 8080 não é um URL válido.
Shane


Deve ser ftps: // localhost: 8080 =)
vp_arth

Ele não parece trabalho: trava na entrada longa (como @aanmarks disse)
cecemel

13

Aqui está outro método.

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


Código educacional! O mecanismo aqui é provavelmente idêntico ao funcionamento new URL(string)do código de Pavlo. Ambos os testes têm resultados idênticos com todos os casos extremos que testei. Eu gosto do código dele porque é mais simples e não envolve a criação de elementos, mas o seu é algumas vezes mais rápido (provavelmente porque não cria o el após o primeiro uso).
precisa saber é

1
Obrigado! Eu implementei seu conselho. No entanto, esteja ciente: navegadores mais antigos e / ou dispositivo móvel WebView podem não ter implementado o elemento <input type = url>; portanto, o valor de entrada seria tratado como um texto comum (sem validação de URL). REF: developer.mozilla.org/pt-BR/docs/Web/HTML/Element/input/url
Panini Luncher

10

(Não tenho representantes para comentar o exemplo do ValidURL ; portanto, poste isso como resposta.)

Embora o uso de URLs relativas ao protocolo não seja incentivado (a URL relativa ao protocolo ), eles são empregados algumas vezes. Para validar tal URL com uma expressão regular, a parte do protocolo pode ser opcional, por exemplo:

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

Como outros observaram, a expressão regular não parece ser a abordagem mais adequada para validar URLs.


A princípio pensei isso foi muito bom, mas não muitos dos testes em mathiasbynens.be/demo/url-regex , e então paira sobreisValidURL("https://d1f4470da51b49289906b3d6cbd65074@app.getsentry.com/13176")
aamarks

Sim, como eu disse, apenas comentei a parte do protocolo. Eu adicionei a cláusula de autenticação para lidar @. Ele não trava nos meus navegadores .
315 ko ko la

Desculpe, eu estava passando por várias delas para avaliá-las e perdi que a sua estivesse comentando a resposta dada. Acho que sua correção até me ajudou a começar quando visitei esta página pela primeira vez. Não está pendurado agora.
precisa saber é

9

Você pode usar a API nativa da URL :

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

3
É muito parecido com a resposta fornecida pelo @pavlo, apenas nomes de variáveis mudou;)
Munim Munna

2
deve realmente haver um método nativo simples para verificar isso agora - essa resposta parecia muito promissora, mas retorna verdadeira desde que o @Basj mencionado acima.
zero_cool 6/09/18

8

Como foi observado, o regex perfeito é ilusório, mas ainda parece ser uma abordagem razoável (alternativas são testes do lado do servidor ou a nova API de URL experimental ). No entanto, as respostas de alta classificação geralmente retornam falsos para URLs comuns, mas ainda pior congelam seu aplicativo / página por minutos em uma string tão simples quanto isURL('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'). Isso foi apontado em alguns comentários, mas provavelmente não foi um valor ruim para ser visto. Pendurar assim torna esse código inutilizável em qualquer aplicação séria. Eu acho que é devido aos conjuntos repetidos sem distinção entre maiúsculas e minúsculas no código como ((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.?)+[a-z]{2,}|' .... Retire o 'i' e ele não trava, mas é claro que não funcionará como desejado. Mas, mesmo com o sinalizador ignorar caso, esses testes rejeitam altos valores unicode que são permitidos.

O melhor já mencionado é:

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

Isso vem do Github segmentio / is-url . O bom de um repositório de código é que você pode ver os testes e quaisquer problemas e também as cadeias de teste executadas nele. Há uma ramificação que permitiria que faltassem protocolos google.com, como , embora você provavelmente esteja fazendo muitas suposições. O repositório foi atualizado e não estou pensando em tentar manter um espelho aqui. Ele foi dividido em testes separados para evitar as repetições do RegEx que podem ser exploradas para ataques do DOS (não acho que você precise se preocupar com isso com o js do lado do cliente, mas precisa se preocupar com a suspensão da página por tanto tempo que o seu visitante sai do seu site).

Já vi outro repositório que pode ser ainda melhor para o isURL em dperini / regex-weburl.js , mas é altamente complexo. Possui uma lista maior de testes de URLs válidos e inválidos. O simples acima ainda passa todos os aspectos positivos e apenas falha em bloquear alguns negativos estranhos, http://a.b--c.de/como também os ips especiais.

Qualquer que seja a sua escolha, execute-o através desta função que adaptei dos testes no dperini / regex-weburl.js, enquanto usa o inpector das Ferramentas de desenvolvedor do navegador.

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

E então teste essa sequência de 'a's.

Veja esta comparação do regex isURL de Mathias Bynens para obter mais informações antes de publicar um regex aparentemente ótimo.


Eu verifiquei sua resposta. Sua resposta está falhando para sdfasdp.ppppppppppp ou seja, retornando true, mas espera é falso
Vikasdeep Singh

1
Eu acho que é um URL válido, estruturalmente. Não sou especialista no padrão, mas não acho que exista um limite para o comprimento da parte .com (eu sei que .online é legítimo).
precisa saber é

1
Eu mal sabia escrever um regex alguns meses atrás. O problema é grave. As duas expressões regulares citadas podem ser concluídas isURL('a'.repeat(100))milhões de vezes / s (a mais complexa da dperini é realmente mais rápida). Algumas das respostas mais altas do formulário ([a-zA-Z] +) * levariam horas para serem concluídas uma vez. Consulte as redo RegEx para obter mais informações.
precisa saber é

6

Não posso comentar sobre o post que é o mais próximo # 5717133 , mas abaixo está a maneira como descobri como fazer o @ tom-gullen regex funcionar.

/^(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
Isso funcionou para mim, mas eu precisava barra invertida. 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

Verifique w3resource.com/javascript-exercises/… para obter mais casos de teste
Kewal Shah

5

Use validator.js

ES6

import isURL from 'validator/lib/isURL'

isURL(string)

Não ES6

var validator = require('validator');

validator.isURL(string)

Você também pode ajustar o comportamento dessa função passando optionsobjeto opcional como o segundo argumento deisURL

Aqui está o optionsobjeto padrão :

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_whiteliste host_blacklistpodem ser matrizes de hosts. Eles também suportam expressões regulares.

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
Agradável! Biblioteca pequena (menos de 40k minificada), biblioteca popular (mais de 3 milhões de downloads semanais em npm), oferece bastante flexibilidade na especificação da validade dos URLs para seu caso de uso específico e tem vários outros validadores além do URL. Esta é de longe a melhor resposta, IMHO.
Javid Jamae 26/03

4

Uma função que eu tenho usado para validar uma URL "string" é:

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

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

Esta função retornará um valor booleano se a string for um URL.

Exemplos:

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

Isso é bastante difícil de fazer com a regex pura, porque os URLs têm muitos "inconvenientes".

  1. Por exemplo, nomes de domínio têm restrições complicadas sobre hífens:

    uma. É permitido ter muitos hífens consecutivos no meio.

    b. mas o primeiro e o último caractere do nome de domínio não podem ser um hífen

    c. O terceiro e o quarto caracteres não podem ser hífen

  2. Da mesma forma, o número da porta pode estar apenas no intervalo de 1-65535. É fácil verificar se você extrai a parte da porta e converte para, intmas é bastante difícil de verificar com uma expressão regular.

  3. Também não há uma maneira fácil de verificar extensões de domínio válidas. Alguns países têm domínios de segundo nível (como 'co.uk'), ou a extensão pode ser uma palavra longa, como '.international'. E novos TLDs são adicionados regularmente. Esse tipo de coisa só pode ser verificado em uma lista codificada. (consulte https://en.wikipedia.org/wiki/Top-level_domain )

  4. Depois, existem URLs de ímã, endereços FTP, etc. Todos esses requisitos diferentes.

No entanto, aqui está uma função que lida com praticamente tudo, exceto:

  • Caso 1. c
  • Aceita qualquer número de porta de 1 a 5 dígitos
  • Aceita qualquer extensão 2-13 caracteres
  • Não aceita ftp, ímã, 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] + ']');
}


1

Eu acho que usar a API de URL nativa é melhor do que um padrão de regex complexo, como sugerido pelo @pavlo. Ele tem algumas desvantagens, que podem ser corrigidas por algum código extra. Essa abordagem falha no seguinte URL válido.

//cdn.google.com/script.js

Podemos adicionar o protocolo ausente antecipadamente para evitar isso. Ele também falha ao detectar o seguinte URL inválido.

http://w
http://..

Então, por que verificar o URL inteiro? podemos apenas verificar o domínio. Peguei emprestado o regex para verificar o domínio a partir daqui .

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

O hostnameatributo é uma string vazia para javascript:void(0), portanto, funciona para isso também, e você também pode adicionar o verificador de endereço IP. Eu gostaria de manter o máximo da API nativa e espero que ela comece a dar suporte a tudo no futuro próximo.


Interessante, mas ainda pode precisar trabalhar no regex, pois agora são introduzidos falsos negativos que new URLnão existem nos testes que fiz. Isso está chamando: http://142.42.1.1 //falsee bloqueando altas cadeias unicode.
precisa saber é

1

A pergunta solicita um método de validação para um URL, como stackoverflow, sem o protocolo ou qualquer ponto no nome do host. Portanto, não é uma questão de validar a sintaxe da URL, mas verificar se é uma URL válida, na verdade, chamando-a.

Tentei vários métodos para saber se o URL verdadeiro existe e é passível de chamada no navegador, mas não encontrei nenhuma maneira de testar com javascript o cabeçalho de resposta da chamada:

  • adicionar um elemento âncora é bom para disparar o click()método.
  • fazer chamada de ajax para o URL desafiador 'GET'é bom, mas tem várias limitações devido a CORSpolíticas e não é o caso de usar ajax, pois, como o URL talvez esteja fora do domínio do meu servidor.
  • o uso da API de busca tem uma solução semelhante ao ajax.
  • outro problema é que eu tenho meu servidor sob httpsprotocolo e lança uma exceção ao chamar URLs não seguros.

Portanto, a melhor solução que posso pensar é obter alguma ferramenta para executar CURLusando javascript, tentando algo parecido curl -I <url>. Infelizmente eu não encontrei nenhum e, de acordo com a aparência, não é possível. Eu aprecio quaisquer comentários sobre isso.

Mas, no final, tenho um servidor em execução PHPe, como uso o Ajax para quase todas as minhas solicitações, escrevi uma função no lado do servidor para executar a solicitação de curl e retornar ao navegador.

Em relação à única palavra url na pergunta 'stackoverflow', ela me levará a https://daniserver.com.ar/stackoverflowonde daniserver.com.ar é meu próprio domínio.


O OP provavelmente deveria ter indicado mais sobre qual era sua intenção. O problema certamente varia de acordo com as suas necessidades e se é mais importante excluir falsos positivos ou incluir falsos negativos. Como o problema é afirmado, parece não haver resposta para mim. Você pode realmente assumir fooe assumir que é http ou https ou .com ou .es ou qualquer um dos inúmeros sufixos? Você continua jogando a pia da cozinha até conseguir uma verdade?
precisa saber é

1

Este parece ser um dos problemas mais difíceis do CS;)

Aqui está outra solução incompleta que funciona bem o suficiente para mim e melhor que as outras que já vi aqui. Estou usando uma entrada [type = url] para isso, a fim de oferecer suporte ao IE11, caso contrário, seria muito mais simples usar window.URL para executar a validação:

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

Para aceitar entradas incompletas, como "www.mydomain.com", também será válido assumindo que o protocolo seja "http" nesses casos e retornando a URL válida se o endereço for válido. Retorna false quando inválido.

Ele também suporta domínios IPv4, mas não IPv6.


1

No meu caso, meu único requisito é que a entrada do usuário não seja interpretada como um link relativo quando colocada no href de uma tag e as respostas aqui sejam um pouco OTT para isso ou URLs permitidos que não atendam aos meus requisitos. é o que eu vou com:

^https?://.+$

A mesma coisa poderia ser alcançada facilmente sem regex.


1

esta trabalhando comigo

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
Esta resposta já foi dada acima há 4 anos por kavitha Reddy.
aamarks 01/06/19

i apenas tornou mais simples e abstrato
HeshamSalama

1

Se você pode alterar o tipo de entrada, acho que essa solução seria muito mais fácil:

Você pode usar de maneira simples type="url"sua entrada e verificá-la checkValidity()em js

Por exemplo:

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

1

Certamente, essa não é a abordagem mais eficaz, mas é legível e fácil de formar para o que você precisar. E é mais fácil adicionar regex / complexidade a partir daqui. Então aqui está uma abordagem muito pragmática

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

TESTE:

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 compilou uma lista de regexes de URL conhecidas com URLs de teste. Há poucas razões para escrever uma nova expressão regular; basta escolher um existente que melhor lhe convier.

Mas a tabela de comparação para essas expressões regulares também mostra que é quase impossível executar a validação de URL com uma única expressão regular. Todas as expressões regulares na lista de Bynens produzem falsos positivos e falsos negativos.

Sugiro que você use um analisador de URL existente (por exemplo, new URL('http://www.example.com/')em JavaScript) e aplique as verificações que deseja executar na forma analisada e normalizada do resp. seus componentes. O uso da URLinterface JavaScript tem o benefício adicional de que ele aceitará apenas os URLs realmente aceitos pelo navegador.

Você também deve ter em mente que os URLs tecnicamente incorretos ainda podem funcionar. Por exemplo http://w_w_w.example.com/, http://www..example.com/, http://123.example.com/todos têm uma parte hostname inválida, mas cada navegador eu sei que vai tentar abri-los sem queixas, e quando você especificar endereços IP para esses nomes inválidos em /etc/hosts/tais URLs vai mesmo trabalhar, mas apenas no seu computador.

Portanto, a questão não é tanto se um URL é válido, mas quais URLs funcionam e devem ser permitidos em um contexto específico.

Se você deseja fazer a validação de URL, há muitos detalhes e casos extremos fáceis de ignorar:

  • Os URLs podem conter credenciais como em http://user:password@www.example.com/.
  • Os números da porta devem estar no intervalo de 0 a 65535, mas você ainda pode excluir a porta curinga 0.
  • Os números de porta podem ter zeros à esquerda, como em http://www.example.com:000080/ .
  • Os endereços IPv4 não estão restritos a 4 números decimais no intervalo de 0 a 255. Você pode usar um a quatro números inteiros e eles podem ser decimais, octais ou hexadecimais. Os URLs https: //010.010.000010.010/ , https: //0x8.0x8.0x0008.0x8/ , https: //8.8.2056/ , https: //8.526344/ , https: // 134744072 / são todos válidos e apenas maneiras criativas de escrever https://8.8.8.8/ .
  • A permissão de endereços de loopback ( http://127.0.0.1/ ), endereços IP privados ( http://192.168.1.1 ), endereços locais de link ( http://169.254.100.200 ) etc. pode afetar a segurança ou privacidade. Se, por exemplo, você os permitir como o endereço dos avatares dos usuários em um fórum, você faz com que os navegadores dos usuários enviem solicitações de rede não solicitadas na rede local e na Internet de coisas que essas solicitações podem causar coisas engraçadas e não tão engraçadas. acontecer em sua casa.
  • Pelas mesmas razões, você pode descartar links para nomes de host não totalmente qualificados, ou seja, nomes de host sem um ponto.
  • Mas nomes de host sempre podem ter um ponto à direita (como em http://www.stackoverflow.com.).
  • A parte do nome do host de um link pode conter colchetes angulares para endereços IPv6 como em http: // [:: 1] .
  • Os endereços IPv6 também têm intervalos para redes privadas ou endereços locais de link etc.
  • Se você bloquear determinados endereços IPv4, lembre-se de que, por exemplo, https://127.0.0.1 e https: // [:: ffff: 127.0.0.1] apontam para o mesmo recurso (se o dispositivo de loopback da sua máquina estiver pronto para IPv6 )
  • A parte do nome do host dos URLs agora pode conter Unicode, para que o intervalo de caracteres [-0-9a-zA-z]definitivamente não seja mais suficiente.
  • Muitos registros para domínios de nível superior definem restrições específicas, por exemplo, no conjunto permitido de caracteres Unicode. Ou eles subdividem seu espaço de nome (como co.ukmuitos outros).
  • Os domínios de nível superior não devem conter dígitos decimais e o hífen não é permitido, a menos que o prefixo do rótulo A do IDN "xn--".
  • Os domínios de nível superior Unicode (e a codificação punycode com "xn--") ainda devem conter apenas letras, mas quem deseja verificar isso em uma regex?

Qual dessas limitações e regras se aplica é uma questão de requisitos e gostos do projeto.

Recentemente, escrevi um validador de URL para um aplicativo Web adequado para URLs fornecidos pelo usuário em fóruns, redes sociais ou similares. Sinta-se à vontade para usá-lo como base para o seu:

Também escrevi uma postagem no blog Os detalhes sangrentos da validação de URLs com informações mais detalhadas.


1

Altero a função para Match +, faça uma alteração aqui com as barras e seu trabalho: (http: // e https)

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

Aqui está apenas uma verificação muito simples para garantir que haja um protocolo válido e a extensão do domínio deve ter dois ou mais caracteres.

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

Se você também precisar oferecer suporte https://localhost:3000, use esta versão modificada do regex do [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

Existem alguns testes usando o construtor de URL que não definem se a entrada é uma string ou um objeto de 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

Atualização 2020. Para expandir as excelentes respostas de @iamnewton e @Fernando Chavez Herrera, comecei a @ser usado no caminho dos URLs.

Portanto, o regex atualizado é:

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

Se você deseja permitir isso na string de consulta e no hash, use:

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

Dito isto, não tenho certeza se há uma regra de white paper não permitida @na string ou no hash da consulta.


0

Já existem muitas respostas, mas aqui está outra contribuição: Extraído diretamente da URLverificação de validade do polyfill, use um inputelemento com type="url"para aproveitar a verificação de validade interna do navegador:

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

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

Fonte

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.