-
-
Save chrisbloom7/6115329 to your computer and use it in GitHub Desktop.
ActiveRecord validator for URLs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'uri_validator' | |
class SomeModel < ActiveRecord::Base | |
validates :url, :presence => true, :uri => { :format => /(^$)|(^(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?([\/].*)?$)/ix } | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'net/http' | |
# Thanks Ilya! http://www.igvita.com/2006/09/07/validating-url-in-ruby-on-rails/ | |
# Original credits: http://blog.inquirylabs.com/2006/04/13/simple-uri-validation/ | |
# HTTP Codes: http://www.ruby-doc.org/stdlib/libdoc/net/http/rdoc/classes/Net/HTTPResponse.html | |
class UriValidator < ActiveModel::EachValidator | |
TIMEOUT_IN_SECONDS = 4 | |
def validate_each(object, attribute, value) | |
raise(ArgumentError, "A regular expression must be supplied as the :format option of the options hash") unless options[:format].nil? or options[:format].is_a?(Regexp) | |
configuration = { :message => "is invalid or not responding", :format => URI::regexp(%w(http https)) } | |
configuration.update(options) | |
if value =~ configuration[:format] | |
begin # check header response | |
Rack::MiniProfiler.step("UriValidator with http.head") do | |
uri = URI.parse(value) | |
http = Net::HTTP.new(uri.host, uri.port) | |
http.continue_timeout = TIMEOUT_IN_SECONDS | |
http.open_timeout = TIMEOUT_IN_SECONDS | |
http.read_timeout = TIMEOUT_IN_SECONDS | |
if uri.scheme == "https" | |
http.use_ssl = true | |
http.verify_mode = OpenSSL::SSL::VERIFY_NONE | |
http.ssl_timeout = TIMEOUT_IN_SECONDS | |
end | |
case http.head(uri.request_uri) | |
when Net::HTTPSuccess, Net::HTTPRedirection then true | |
else object.errors.add(attribute, configuration[:message]) and false | |
end | |
end | |
rescue # Recover on DNS or timeout failures.. | |
object.errors.add(attribute, configuration[:message]) and false | |
end | |
else | |
object.errors.add(attribute, configuration[:message]) and false | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment