Come verificare se un URL è valido


93

Come posso verificare se una stringa è un URL valido?

Per esempio:

http://hello.it => yes
http:||bra.ziz, => no

Se si tratta di un URL valido come posso verificare se è relativo a un file immagine?


l'URL che hai fornito sembra essere un URL assoluto, cosa intendi con relativo a un file immagine
johannes

Ho pubblicato un UriValidator con le specifiche .
JJD

Risposte:


177

Usa il URImodulo distribuito con Ruby:

require 'uri'

if url =~ URI::regexp
    # Correct URL
end

Come ha detto Alexander Günther nei commenti, controlla se una stringa contiene un URL.

Per verificare se la stringa è un URL, utilizza:

url =~ /\A#{URI::regexp}\z/

Se vuoi solo controllare gli URL web ( httpo https), usa questo:

url =~ /\A#{URI::regexp(['http', 'https'])}\z/

24
Questo non sembra funzionare: 'http://:5984/asdf' =~ URI::regexped 'http::5984/asdf' =~ URI::regexpentrambi restituiscono 0. Mi aspettavo che restituissero zero perché nessuno di loro è URI valido.
awendt

4
Non è: 5984 porta 5984 su localhost?
mxcl

3
In realtà controlla se una variabile contiene un URL valido. Accetterà " example com" come URL valido. Perché ne contiene uno. Ma non è utile se ti aspetti che l'intera cosa sia l'URL.
Alexander Günther

2
gotqn: Questo non è un URL valido secondo RFC 1738.
Mikael S

12
Non usarlo, è così brutto che "http:"passa questa regexp.
smathy

43

Simile alle risposte sopra, trovo che l'uso di questa regex sia leggermente più preciso:

URI::DEFAULT_PARSER.regexp[:ABS_URI]

Ciò invaliderà gli URL con spazi, al contrario di quelli URI.regexpche consentono spazi per qualche motivo.

Recentemente ho trovato un collegamento fornito per i diversi rgexps URI. Puoi accedere a qualsiasi di URI::DEFAULT_PARSER.regexp.keysdirettamente da URI::#{key}.

Ad esempio, è :ABS_URIpossibile accedere all'espressione regolare da URI::ABS_URI.


3
Se hai intenzione di utilizzare URI.parse in qualsiasi momento, questa è sicuramente la strada da percorrere. URI :: regexp corrisponde a determinati URL che non funzioneranno se in seguito si utilizzerà URI.parse. Grazie per il consiglio.
markquezada

Purtroppo, questo è disponibile solo su Ruby 1.9, non 1.8.
Steve Madsen,

1
Ma, questo funziona: /^#{URI.regexp}$/. Il problema è che URI.regexpnon si fissa. Una stringa con uno spazio non convalida lo spazio come parte dell'URI, ma tutto ciò che conduce allo spazio. Se quel frammento sembra un URI valido, la corrispondenza ha esito positivo.
Steve Madsen,

3
Applicare il commento di awendt alle tue proposte: 'http://:5984/asdf' =~ URI::DEFAULT_PARSER.regexp[:ABS_URI]dà 0, non nullo; 'http::5984/asdf'=~ URI::DEFAULT_PARSER.regexp[:ABS_URI]dà 0; 'http://:5984/asdf' =~ /^#{URI.regexp}$/dà 0; 'http::5984/asdf' =~ /^#{URI.regexp}$/dà anche 0. Nessuna delle espressioni regolari di cui sopra è completamente corretta, tuttavia falliscono solo in situazioni molto molto strane e questo non è un grosso problema nella maggior parte dei casi.
skalee

1
Cordiali saluti, URI::DEFAULT_PARSER.regexp[:ABS_URI]è identico a/\A\s*#{URI::regexp}\s*\z/
aidan

34

Il problema con le risposte attuali è che un URI non è un URL .

Un URI può essere ulteriormente classificato come un localizzatore, un nome o entrambi. Il termine "Uniform Resource Locator" (URL) si riferisce al sottoinsieme di URI che, oltre a identificare una risorsa, forniscono un mezzo per localizzare la risorsa descrivendo il suo meccanismo di accesso primario (ad esempio, la sua "posizione" di rete).

Poiché gli URL sono un sottoinsieme di URI, è chiaro che la corrispondenza specifica per gli URI corrisponderà correttamente a valori indesiderati. Ad esempio, URN :

 "urn:isbn:0451450523" =~ URI::regexp
 => 0 

Detto questo, per quanto ne so, Ruby non ha un modo predefinito per analizzare gli URL, quindi molto probabilmente avrai bisogno di una gemma per farlo. Se hai bisogno di abbinare URL specificamente in formato HTTP o HTTPS, potresti fare qualcosa del genere:

uri = URI.parse(my_possible_url)
if uri.kind_of?(URI::HTTP) or uri.kind_of?(URI::HTTPS)
  # do your stuff
end

@Philip è stato utile e appropriato. Grazie mille!
fotanus

2
uri.kind_of?(URI::HTTP)sembra essere sufficiente per entrambi i casi (http e https), almeno in ruby ​​1.9.3.
Andrea Salicetti

soffre ancora dei problemi descritti da @skalee sotto la risposta dei
jonuts

1
Riepilogo, URI.parse(string_to_be_checked).kind_of?(URI::HTTP)fa bene il lavoro.
ben

19

Preferisco la gemma indirizzabile . Ho scoperto che gestisce gli URL in modo più intelligente.

require 'addressable/uri'

SCHEMES = %w(http https)

def valid_url?(url)
  parsed = Addressable::URI.parse(url) or return false
  SCHEMES.include?(parsed.scheme)
rescue Addressable::URI::InvalidURIError
  false
end

3
Ho appena alimentato Addressable :: URI.parse () con le stringhe più strane per vedere cosa rifiuta. Accettava cose pazze. Tuttavia la prima stringa che non ha accettato è stata ":-)". Hmm.
mvw

1
Come fa a ottenere così tanti voti positivi? Addressable::URI.parsenon restituisce nil con input non valido.
garbagecollector

11

Questa è una voce abbastanza vecchia, ma ho pensato di andare avanti e contribuire:

String.class_eval do
    def is_valid_url?
        uri = URI.parse self
        uri.kind_of? URI::HTTP
    rescue URI::InvalidURIError
        false
    end
end

Ora puoi fare qualcosa come:

if "http://www.omg.wtf".is_valid_url?
    p "huzzah!"
end

2
Funziona molto meglio delle soluzioni di cui sopra. Non ha gli avvertimenti sopra elencati e inoltre non accetta uris come javascript: alert ('spam').
bchurchill

2
ma corrisponde anche http:/, il che potrebbe non essere quello che desideri.
Bo Jeanes

10

Per me, utilizzo questa espressione regolare:

/^(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$/ix

Opzione:

  • i - case insensitive
  • x - ignora gli spazi bianchi in regex

Puoi impostare questo metodo per controllare la convalida dell'URL:

def valid_url?(url)
  url_regexp = /^(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$/ix
  url =~ url_regexp ? true : false
end

Per usarlo:

valid_url?("http://stackoverflow.com/questions/1805761/check-if-url-is-valid-ruby")

Test con URL sbagliati:

  • http://ruby3arabi - il risultato non è valido
  • http://http://ruby3arabi.com - il risultato non è valido
  • http:// - il risultato non è valido

Prova con gli URL corretti:

  • http://ruby3arabi.com - il risultato è valido
  • http://www.ruby3arabi.com - il risultato è valido
  • https://www.ruby3arabi.com - il risultato è valido
  • https://www.ruby3arabi.com/article/1 - il risultato è valido
  • https://www.ruby3arabi.com/websites/58e212ff6d275e4bf9000000?locale=en - il risultato è valido

Quanto segue è contrassegnato come valido: "http://test.com\n<script src=\"nasty.js\">"e qualsiasi dominio che utilizza uno dei 683 TLD di lunghezza superiore a 5 caratteri o che ha due o più trattini consecutivi è contrassegnato come non valido. Sono consentiti numeri di porta al di fuori dell'intervallo 0-65535. Ovviamente gli indirizzi FTP e IP non sono consentiti, ma vale la pena notare.
aidan

1
facilmente la migliore soluzione più applicabile qui per un rapido controllo dell'URL. grazie
qualche direzione

4

Questo è un po 'vecchio ma ecco come lo faccio. Usa il modulo URI di Ruby per analizzare l'URL. Se può essere analizzato, è un URL valido. (Ma questo non significa accessibile.)

L'URI supporta molti schemi, inoltre puoi aggiungere tu stesso schemi personalizzati:

irb> uri = URI.parse "http://hello.it" rescue nil
=> #<URI::HTTP:0x10755c50 URL:http://hello.it>

irb> uri.instance_values
=> {"fragment"=>nil,
 "registry"=>nil,
 "scheme"=>"http",
 "query"=>nil,
 "port"=>80,
 "path"=>"",
 "host"=>"hello.it",
 "password"=>nil,
 "user"=>nil,
 "opaque"=>nil}

irb> uri = URI.parse "http:||bra.ziz" rescue nil
=> nil


irb> uri = URI.parse "ssh://hello.it:5888" rescue nil
=> #<URI::Generic:0x105fe938 URL:ssh://hello.it:5888>
[26] pry(main)> uri.instance_values
=> {"fragment"=>nil,
 "registry"=>nil,
 "scheme"=>"ssh",
 "query"=>nil,
 "port"=>5888,
 "path"=>"",
 "host"=>"hello.it",
 "password"=>nil,
 "user"=>nil,
 "opaque"=>nil}

Vedere la documentazione per ulteriori informazioni sul modulo URI.


Mi sono imbattuto in questo cercando di riparare un segfault. L'utilizzo URI.parseera in realtà la causa di ciò in Ruby 2.5.5 - Sono passato alla risposta @jonuts di seguito se non ti dispiace che alcuni casi strani cadono. Per i miei scopi non mi importava, quindi era l'ideale.
el n00b

3

In generale,

/^#{URI::regexp}$/

funzionerà bene, ma se vuoi solo abbinare httpo https, puoi passarli come opzioni al metodo:

/^#{URI::regexp(%w(http https))}$/

Questo tende a funzionare un po 'meglio, se vuoi rifiutare protocolli come ftp://.


-2

Potresti anche usare un'espressione regolare, forse qualcosa come http://www.geekzilla.co.uk/View2D3B0109-C1B2-4B4E-BFFD-E8088CBC85FD.htm supponendo che questa regex sia corretta (non l'ho completamente controllata) il seguente lo farà mostrare la validità dell'url.

url_regex = Regexp.new("((https?|ftp|file):((//)|(\\\\))+[\w\d:\#@%/;$()~_?\+-=\\\\.&]*)")

urls = [
    "http://hello.it",
    "http:||bra.ziz"
]

urls.each { |url|
    if url =~ url_regex then
        puts "%s is valid" % url
    else
        puts "%s not valid" % url
    end
}

L'esempio sopra restituisce:

http://hello.it is valid
http:||bra.ziz not valid

5
E lo schema mailto? O telnet, gopher, nntp, rsync, ssh o uno qualsiasi degli altri schemi? Gli URL sono un po 'più complicati dei soli HTTP e FTP.
mu è troppo breve

Scrivere regex per convalidare gli URL è difficile. Perché preoccuparsi?
Rimian

@Rimian, devi preoccuparti perché tutto quello che URIpuoi fare è in effetti rotto. Vedi i commenti sotto le tante risposte votate sopra. Non sono sicuro che la risposta di Janie sia giusta, ma si spera che la gente la consideri più seriamente. TBH finisco per fare url.start_with?("http://") || url.start_with?("https://")perché ho bisogno solo di HTTP e gli utenti dovrebbero essere responsabili di utilizzare gli URL appropriati.
akostadinov
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.