Comment puis-je vérifier si une chaîne est une URL valide?
Par exemple:
http://hello.it => yes
http:||bra.ziz, => no
S'il s'agit d'une URL valide, comment puis-je vérifier si elle est relative à un fichier image?
Comment puis-je vérifier si une chaîne est une URL valide?
Par exemple:
http://hello.it => yes
http:||bra.ziz, => no
S'il s'agit d'une URL valide, comment puis-je vérifier si elle est relative à un fichier image?
Réponses:
Utilisez le URI
module distribué avec Ruby:
require 'uri'
if url =~ URI::regexp
# Correct URL
end
Comme Alexander Günther l'a dit dans les commentaires, il vérifie si une chaîne contient une URL.
Pour vérifier si la chaîne est une URL, utilisez:
url =~ /\A#{URI::regexp}\z/
Si vous souhaitez uniquement vérifier les URL Web ( http
ou https
), utilisez ceci:
url =~ /\A#{URI::regexp(['http', 'https'])}\z/
'http://:5984/asdf' =~ URI::regexp
et les 'http::5984/asdf' =~ URI::regexp
deux renvoient 0. Je m'attendais à ce qu'ils renvoient nil car aucun d'entre eux n'est un URI valide.
"http:"
cette expression rationnelle passe.
Semblable aux réponses ci-dessus, je trouve que l'utilisation de cette expression régulière est légèrement plus précise:
URI::DEFAULT_PARSER.regexp[:ABS_URI]
Cela invalidera les URL avec des espaces, par opposition à URI.regexp
ce qui autorise les espaces pour une raison quelconque.
J'ai récemment trouvé un raccourci fourni pour les différents rgexps URI. Vous pouvez accéder URI::DEFAULT_PARSER.regexp.keys
directement à partir de URI::#{key}
.
Par exemple, l' :ABS_URI
expression rationnelle est accessible depuis URI::ABS_URI
.
/^#{URI.regexp}$/
. Le problème est que URI.regexp
cela ne s'ancre pas. Une chaîne avec un espace ne valide pas l'espace en tant que partie de l'URI, mais tout ce qui mène à l'espace. Si ce fragment ressemble à un URI valide, la correspondance réussit.
'http://:5984/asdf' =~ URI::DEFAULT_PARSER.regexp[:ABS_URI]
donne 0, pas nul; 'http::5984/asdf'=~ URI::DEFAULT_PARSER.regexp[:ABS_URI]
donne 0; 'http://:5984/asdf' =~ /^#{URI.regexp}$/
donne 0; 'http::5984/asdf' =~ /^#{URI.regexp}$/
donne également 0. Aucune des expressions rationnelles ci-dessus n'est entièrement correcte, mais elles échouent uniquement dans des situations très très étranges et ce n'est pas un gros problème dans la plupart des cas.
URI::DEFAULT_PARSER.regexp[:ABS_URI]
est identique à/\A\s*#{URI::regexp}\s*\z/
Le problème avec les réponses actuelles est qu'un URI n'est pas une URL .
Un URI peut être davantage classé en tant que localisateur, nom ou les deux. Le terme «Uniform Resource Locator» (URL) fait référence au sous-ensemble d'URI qui, en plus d'identifier une ressource, fournissent un moyen de localiser la ressource en décrivant son mécanisme d'accès principal (par exemple, son «emplacement» réseau).
Étant donné que les URL sont un sous-ensemble d'URI, il est clair que la correspondance spécifiquement pour les URI correspondra avec succès aux valeurs indésirables. Par exemple, les URN :
"urn:isbn:0451450523" =~ URI::regexp
=> 0
Cela étant dit, pour autant que je sache, Ruby n'a pas de méthode par défaut pour analyser les URL, vous aurez donc probablement besoin d'une gemme pour le faire. Si vous avez besoin de faire correspondre des URL spécifiquement au format HTTP ou HTTPS, vous pouvez faire quelque chose comme ceci:
uri = URI.parse(my_possible_url)
if uri.kind_of?(URI::HTTP) or uri.kind_of?(URI::HTTPS)
# do your stuff
end
uri.kind_of?(URI::HTTP)
semble être suffisant pour les deux cas (http et https), du moins dans ruby 1.9.3.
URI.parse(string_to_be_checked).kind_of?(URI::HTTP)
fait bien le travail.
http:///neopets.com
ce qui est malheureusement également valide. Vérifier la présence d'un nom d'hôte corrige ceci:uri = URI(str) ; %w[http https].include?(uri.scheme) && !uri.host.nil?
Je préfère le joyau adressable . J'ai trouvé qu'il gère les URL de manière plus 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
Addressable::URI.parse
ne renvoie pas nil avec une entrée invalide.
C'est une entrée assez ancienne, mais j'ai pensé que j'irais de l'avant et contribuerais:
String.class_eval do
def is_valid_url?
uri = URI.parse self
uri.kind_of? URI::HTTP
rescue URI::InvalidURIError
false
end
end
Vous pouvez maintenant faire quelque chose comme:
if "http://www.omg.wtf".is_valid_url?
p "huzzah!"
end
http:/
, ce qui n'est peut-être pas ce que vous voulez.
Pour moi, j'utilise cette expression régulière:
/^(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$/ix
Option:
i
- insensible à la cassex
- ignorer les espaces dans les regexVous pouvez définir cette méthode pour vérifier la validation d'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
Pour l'utiliser:
valid_url?("http://stackoverflow.com/questions/1805761/check-if-url-is-valid-ruby")
Test avec de mauvaises URL:
http://ruby3arabi
- le résultat est invalidehttp://http://ruby3arabi.com
- le résultat est invalidehttp://
- le résultat est invalideTestez avec les URL correctes:
http://ruby3arabi.com
- le résultat est validehttp://www.ruby3arabi.com
- le résultat est validehttps://www.ruby3arabi.com
- le résultat est validehttps://www.ruby3arabi.com/article/1
- le résultat est validehttps://www.ruby3arabi.com/websites/58e212ff6d275e4bf9000000?locale=en
- le résultat est valide"http://test.com\n<script src=\"nasty.js\">"
et tout domaine qui utilise l'un des 683 TLD de plus de 5 caractères, ou a deux traits d'union consécutifs ou plus, est marqué comme invalide. Les numéros de port en dehors de la plage 0-65535 sont autorisés. Les adresses FTP et IP sont évidemment interdites, mais il convient de le noter.
C'est un peu vieux mais voici comment je le fais. Utilisez le module URI de Ruby pour analyser l'URL. Si elle peut être analysée, c'est une URL valide. (Mais cela ne veut pas dire accessible.)
L'URI prend en charge de nombreux schémas, et vous pouvez ajouter vous-même des schémas personnalisés:
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}
Consultez la documentation pour plus d'informations sur le module URI.
URI.parse
était en fait la cause dans Ruby 2.5.5 - Je suis passé à la réponse @jonuts ci-dessous si cela ne vous dérange pas que certains cas étranges échouent. Pour mes besoins, je m'en fichais donc c'était idéal.
En général,
/^#{URI::regexp}$/
fonctionnera bien, mais si vous ne voulez correspondre qu'à http
ou https
, vous pouvez les transmettre en tant qu'options à la méthode:
/^#{URI::regexp(%w(http https))}$/
Cela a tendance à fonctionner un peu mieux si vous souhaitez rejeter des protocoles comme ftp://
.
Vous pouvez également utiliser une expression régulière, peut-être quelque chose comme http://www.geekzilla.co.uk/View2D3B0109-C1B2-4B4E-BFFD-E8088CBC85FD.htm en supposant que cette expression régulière est correcte (je ne l'ai pas complètement vérifié), ce qui suit sera montrer la validité de l'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'exemple ci-dessus génère:
http://hello.it is valid
http:||bra.ziz not valid
URI
pouvez faire est en fait cassé. Voir les commentaires sous les nombreuses réponses positives ci-dessus. Je ne sais pas si la réponse de Janie est juste, mais j'espère que les gens la considéreront plus sérieusement. TBH Je finis par faire url.start_with?("http://") || url.start_with?("https://")
parce que je n'ai besoin que de HTTP et que les utilisateurs devraient être responsables d'utiliser les URL appropriées.