Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .rspec
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
-cfs
--format documentation
--color
1 change: 1 addition & 0 deletions .ruby-gemset
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
url_validation
1 change: 1 addition & 0 deletions .ruby-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
2.1.4
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
source :rubygems
source 'https://rubygems.org'

gem 'addressable', :require => 'addressable/uri' # for unicode URIs
gem 'activesupport'
Expand Down
113 changes: 78 additions & 35 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,43 +1,86 @@
GEM
remote: http://rubygems.org/
remote: https://rubygems.org/
specs:
RedCloth (4.2.7)
activemodel (3.0.7)
activesupport (= 3.0.7)
builder (~> 2.1.2)
i18n (~> 0.5.0)
activerecord (3.0.7)
activemodel (= 3.0.7)
activesupport (= 3.0.7)
arel (~> 2.0.2)
tzinfo (~> 0.3.23)
activesupport (3.0.7)
addressable (2.2.6)
arel (2.0.10)
builder (2.1.2)
diff-lcs (1.1.2)
git (1.2.5)
httpi (0.9.4)
pyu-ntlm-http (>= 0.1.3.1)
RedCloth (4.2.9)
activemodel (4.1.7)
activesupport (= 4.1.7)
builder (~> 3.1)
activerecord (4.1.7)
activemodel (= 4.1.7)
activesupport (= 4.1.7)
arel (~> 5.0.0)
activesupport (4.1.7)
i18n (~> 0.6, >= 0.6.9)
json (~> 1.7, >= 1.7.7)
minitest (~> 5.1)
thread_safe (~> 0.1)
tzinfo (~> 1.1)
addressable (2.3.6)
arel (5.0.1.20140414130214)
builder (3.2.2)
descendants_tracker (0.0.4)
thread_safe (~> 0.3, >= 0.3.1)
diff-lcs (1.2.5)
faraday (0.9.0)
multipart-post (>= 1.2, < 3)
git (1.2.8)
github_api (0.12.2)
addressable (~> 2.3)
descendants_tracker (~> 0.0.4)
faraday (~> 0.8, < 0.10)
hashie (>= 3.3)
multi_json (>= 1.7.5, < 2.0)
nokogiri (~> 1.6.3)
oauth2
hashie (3.3.1)
highline (1.6.21)
httpi (2.2.7)
rack
i18n (0.5.0)
jeweler (1.6.0)
bundler (~> 1.0.0)
i18n (0.6.11)
jeweler (2.0.1)
builder
bundler (>= 1.0)
git (>= 1.2.5)
github_api
highline (>= 1.6.15)
nokogiri (>= 1.5.10)
rake
pyu-ntlm-http (0.1.3.1)
rack (1.3.0)
rake (0.9.0)
rspec (2.6.0)
rspec-core (~> 2.6.0)
rspec-expectations (~> 2.6.0)
rspec-mocks (~> 2.6.0)
rspec-core (2.6.3)
rspec-expectations (2.6.0)
diff-lcs (~> 1.1.2)
rspec-mocks (2.6.0)
tzinfo (0.3.27)
yard (0.7.1)
rdoc
json (1.8.1)
jwt (1.0.0)
mini_portile (0.6.1)
minitest (5.4.2)
multi_json (1.10.1)
multi_xml (0.5.5)
multipart-post (2.0.0)
nokogiri (1.6.4.1)
mini_portile (~> 0.6.0)
oauth2 (1.0.0)
faraday (>= 0.8, < 0.10)
jwt (~> 1.0)
multi_json (~> 1.3)
multi_xml (~> 0.5)
rack (~> 1.2)
rack (1.5.2)
rake (10.3.2)
rdoc (4.1.2)
json (~> 1.4)
rspec (3.1.0)
rspec-core (~> 3.1.0)
rspec-expectations (~> 3.1.0)
rspec-mocks (~> 3.1.0)
rspec-core (3.1.7)
rspec-support (~> 3.1.0)
rspec-expectations (3.1.2)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.1.0)
rspec-mocks (3.1.3)
rspec-support (~> 3.1.0)
rspec-support (3.1.2)
thread_safe (0.3.4)
tzinfo (1.2.2)
thread_safe (~> 0.1)
yard (0.8.7.6)

PLATFORMS
ruby
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.0.0
1.1.0
25 changes: 14 additions & 11 deletions lib/url_validation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
require 'httpi'
require 'active_support/core_ext/hash/except'
require 'active_model/validator'
require 'active_support/core_ext/array/wrap'

# Validates URLs. Uses the following I18n error message keys:
#
Expand Down Expand Up @@ -59,7 +60,6 @@
# h3. Other options
#
# | @:request_callback@ | A proc that receives the request object (for ==HTTP(S)== requests, the @HTTPI::Request@ object) before it is executed. You can use this proc to set, e.g., custom headers or timeouts on the request. |
# | @:response_callback@ | A proc that receives the response object after it is executed by @:check_path@, when it is enabled. This is useful for checking redirect URL's, etc. |

class UrlValidator < ActiveModel::EachValidator
# @private
Expand Down Expand Up @@ -120,23 +120,27 @@ class UrlValidator < ActiveModel::EachValidator

# @private
def validate_each(record, attribute, value)
return if options[:allow_nil] and value.nil?
return if options[:allow_blank] and value.blank?

uri = Addressable::URI.parse(value)
if uri.scheme.nil? and options[:default_scheme] then
uri = Addressable::URI.parse("#{options[:default_scheme]}://#{value}")
return if value.blank?

begin
uri = Addressable::URI.parse(value)
if uri.scheme.nil? and options[:default_scheme] then
uri = Addressable::URI.parse("#{options[:default_scheme]}://#{value}")
end
rescue Addressable::URI::InvalidURIError
record.errors.add(attribute, options[:invalid_url_message] || :invalid_url) unless url_format_valid?(uri, options)
return
end

record.errors.add(attribute, options[:invalid_url_message] || :invalid_url) unless url_format_valid?(uri, options)
record.errors.add(attribute, options[:url_not_accessible_message] || :url_not_accessible) unless response = url_accessible?(uri, options)
record.errors.add(attribute, options[:url_invalid_response_message] || :url_invalid_response) unless url_response_valid?(response, record, attribute, value, options)
record.errors.add(attribute, options[:url_invalid_response_message] || :url_invalid_response) unless url_response_valid?(response, options)
end

private

def url_format_valid?(uri, options)
return false unless Array.wrap(options[:scheme] || %w( http https )).include?(uri.scheme)
return false unless Array.wrap(options[:scheme] || %w( http https )).include?(uri.try(:scheme))

case uri.scheme
when 'http', 'https'
Expand Down Expand Up @@ -175,9 +179,8 @@ def http_url_accessible?(uri, options)
return false
end

def url_response_valid?(response, record, attribute, value, options)
def url_response_valid?(response, options)
return true unless response.kind_of?(HTTPI::Response) and options[:check_path]
options[:response_callback].call(response, record, attribute, value) if options[:response_callback].respond_to?(:call)
response_codes = options[:check_path] == true ? [400..499, 500..599] : Array.wrap(options[:check_path]).flatten
return response_codes.none? do |code| # it's good if it's not a bad response
case code # and it's a bad response if...
Expand Down
Loading