La validation d'une URL est un travail délicat. C'est aussi une demande très large.
Que voulez-vous faire, exactement? Voulez-vous valider le format de l'URL, l'existence, ou quoi? Il y a plusieurs possibilités, selon ce que vous voulez faire.
Une expression régulière peut valider le format de l'URL. Mais même une expression régulière complexe ne peut pas garantir que vous utilisez une URL valide.
Par exemple, si vous utilisez une expression régulière simple, elle rejettera probablement l'hôte suivant
http://invalid##host.com
mais elle permettra
http://invalid-host.foo
qui est un hôte valide, mais pas un domaine valide si l'on considère les TLD existants. En effet, la solution fonctionnerait si vous voulez valider le nom d'hôte, pas le domaine car le suivant est un nom d'hôte valide
http://host.foo
ainsi que le suivant
http://localhost
Maintenant, laissez-moi vous donner quelques solutions.
Si vous voulez valider un domaine, alors vous devez oublier les expressions régulières. La meilleure solution disponible actuellement est la Public Suffix List, une liste maintenue par Mozilla. J'ai créé une bibliothèque Ruby pour analyser et valider les domaines par rapport à la Public Suffix List, et elle s'appelle PublicSuffix.
Si vous voulez valider le format d'un URI/URL, alors vous voudrez peut-être utiliser des expressions régulières. Au lieu d'en rechercher une, utilisez la méthode Ruby intégrée URI.parse
.
require 'uri'
def valid_url?(uri)
uri = URI.parse(uri) && uri.host.present?
rescue URI::InvalidURIError
false
end
Vous pouvez même décider de le rendre plus restrictif. Par exemple, si vous voulez que l'URL soit une URL HTTP/HTTPS, vous pouvez rendre la validation plus précise.
require 'uri'
def valid_url?(url)
uri = URI.parse(url)
uri.is_a?(URI::HTTP) && uri.host.present?
rescue URI::InvalidURIError
false
Bien sûr, il y a des tonnes d'améliorations que vous pouvez apporter à cette méthode, y compris la vérification d'un chemin ou d'un schéma.
Enfin, vous pouvez également empaqueter ce code dans un validateur :
class HttpUrlValidator < ActiveModel::EachValidator
def self.compliant?(value)
uri = URI.parse(value)
uri.is_a?(URI::HTTP) && uri.host.present?
rescue URI::InvalidURIError
false
end
def validate_each(record, attribute, value)
unless value.present? && self.class.compliant?(value)
record.errors.add(attribute, "n'est pas une URL HTTP valide")
end
end
end
# dans le modèle
validates :example_attribute, http_url: true
Note pour les nouvelles versions d'URI (c'est-à-dire 0.12.1)
.present?
/ .blank?
serait un moyen plus précis de valider les hôtes, au lieu d'utiliser uri.host.nil?
ou simplement if uri.host
auparavant (c'est-à-dire URI v 0.11).
Exemple pour URI.parse("https:///394") :
- Nouvelle version d'URI (0.12),
host
renverra une chaîne vide, et /394
deviendra un chemin. #
- Ancienne version d'URI (0.11),
host
renverra une chaîne vide, et /394
deviendra également un chemin. #
0 votes
Connexe : stackoverflow.com/questions/1805761/…