La convalida di un URL è un lavoro complicato. È anche una richiesta molto ampia.
Cosa vuoi fare esattamente? Vuoi convalidare il formato dell'URL, l'esistenza o cosa? Ci sono diverse possibilità, a seconda di cosa vuoi fare.
Un'espressione regolare può convalidare il formato dell'URL. Ma anche un'espressione regolare complessa non può garantire che si tratti di un URL valido.
Ad esempio, se prendi una semplice espressione regolare, probabilmente rifiuterà il seguente host
http://invalid##host.com
ma permetterà
http://invalid-host.foo
questo è un host valido, ma non un dominio valido se si considerano i TLD esistenti. In effetti, la soluzione funzionerebbe se si desidera convalidare il nome host, non il dominio perché il seguente è un nome host valido
http://host.foo
così come il seguente
http://localhost
Ora, lascia che ti dia alcune soluzioni.
Se vuoi convalidare un dominio, devi dimenticare le espressioni regolari. La migliore soluzione disponibile al momento è la Public Suffix List, una lista mantenuta da Mozilla. Ho creato una libreria Ruby per analizzare e convalidare i domini rispetto all'elenco dei suffissi pubblici e si chiama PublicSuffix .
Se desideri convalidare il formato di un URI / URL, potresti voler utilizzare espressioni regolari. Invece di cercarne uno, usa il URI.parse
metodo Ruby integrato .
require 'uri'
def valid_url?(uri)
uri = URI.parse(uri) && !uri.host.nil?
rescue URI::InvalidURIError
false
end
Puoi anche decidere di renderlo più restrittivo. Ad esempio, se desideri che l'URL sia un URL HTTP / HTTPS, puoi rendere la convalida più accurata.
require 'uri'
def valid_url?(url)
uri = URI.parse(url)
uri.is_a?(URI::HTTP) && !uri.host.nil?
rescue URI::InvalidURIError
false
end
Naturalmente, ci sono tonnellate di miglioramenti che puoi applicare a questo metodo, incluso il controllo di un percorso o di uno schema.
Ultimo ma non meno importante, puoi anche impacchettare questo codice in un validatore:
class HttpUrlValidator < ActiveModel::EachValidator
def self.compliant?(value)
uri = URI.parse(value)
uri.is_a?(URI::HTTP) && !uri.host.nil?
rescue URI::InvalidURIError
false
end
def validate_each(record, attribute, value)
unless value.present? && self.class.compliant?(value)
record.errors.add(attribute, "is not a valid HTTP URL")
end
end
end
# in the model
validates :example_attribute, http_url: true