Weryfikacja adresu URL to trudna praca. To także bardzo szeroka prośba.
Co dokładnie chcesz zrobić? Czy chcesz sprawdzić format adresu URL, istnienie czy co? Istnieje kilka możliwości, w zależności od tego, co chcesz zrobić.
Wyrażenie regularne może zweryfikować format adresu URL. Ale nawet złożone wyrażenie regularne nie może zapewnić, że masz do czynienia z prawidłowym adresem URL.
Na przykład, jeśli weźmiesz proste wyrażenie regularne, prawdopodobnie odrzuci ono następujący host
http://invalid##host.com
ale to pozwoli
http://invalid-host.foo
to jest prawidłowy host, ale nie jest to prawidłowa domena, jeśli wziąć pod uwagę istniejące TLD. Rzeczywiście, rozwiązanie zadziałałoby, gdybyś chciał zweryfikować nazwę hosta, a nie domenę, ponieważ następująca jest prawidłową nazwą hosta
http://host.foo
jak również następny
http://localhost
Pozwólcie, że przedstawię wam kilka rozwiązań.
Jeśli chcesz zweryfikować domenę, musisz zapomnieć o wyrażeniach regularnych. Najlepszym obecnie dostępnym rozwiązaniem jest Public Suffix List, lista utrzymywana przez Mozillę. Stworzyłem bibliotekę Ruby do analizowania i sprawdzania poprawności domen względem listy sufiksów publicznych i nazywa się PublicSuffix .
Jeśli chcesz sprawdzić poprawność formatu identyfikatora URI / adresu URL, możesz użyć wyrażeń regularnych. Zamiast szukać jednego, użyj wbudowanej URI.parse
metody Ruby .
require 'uri'
def valid_url?(uri)
uri = URI.parse(uri) && !uri.host.nil?
rescue URI::InvalidURIError
false
end
Możesz nawet zdecydować, czy będzie bardziej restrykcyjny. Na przykład, jeśli chcesz, aby adres URL był adresem URL HTTP / HTTPS, możesz zwiększyć dokładność weryfikacji.
require 'uri'
def valid_url?(url)
uri = URI.parse(url)
uri.is_a?(URI::HTTP) && !uri.host.nil?
rescue URI::InvalidURIError
false
end
Oczywiście istnieje mnóstwo ulepszeń, które możesz zastosować w tej metodzie, w tym sprawdzenie ścieżki lub schematu.
Wreszcie, możesz również spakować ten kod do walidatora:
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