Skip to content

Commit

Permalink
AROR-421 Adding validation for whitesepace
Browse files Browse the repository at this point in the history
  • Loading branch information
schallereqo committed Apr 13, 2017
1 parent 135cf74 commit ddda6ee
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 43 deletions.
26 changes: 13 additions & 13 deletions lib/url_validation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,8 @@ class UrlValidator < ActiveModel::EachValidator
:insufficient_storage => 507,
:not_extended => 510
}


# @private
def validate_each(record, attribute, value)
return if value.blank?
Expand All @@ -128,41 +128,41 @@ def validate_each(record, attribute, value)
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)
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, options)
end

private

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

case uri.scheme
when 'http', 'https'
return http_url_format_valid?(uri)
else
return true
end
end

def http_url_format_valid?(uri)
uri.host.present? and not uri.path.nil?
uri.host.present? and not uri.path.nil? and not uri.host.match(/\s/)
end

def url_accessible?(uri, options)
return true unless options[:check_host] or options[:check_path]

check_host = options[:check_host]
check_host ||= %w( http https ) if options[:check_path]
if (schemes = Array.wrap(check_host)) and schemes.all? { |scheme| scheme.kind_of?(String) } then
return true unless schemes.include?(uri.scheme)
end

case uri.scheme
when 'http', 'https'
return http_url_accessible?(uri, options)
Expand All @@ -178,7 +178,7 @@ def http_url_accessible?(uri, options)
rescue
return false
end

def url_response_valid?(response, options)
return true unless response.kind_of?(HTTPI::Response) and options[:check_path]
response_codes = options[:check_path] == true ? [400..499, 500..599] : Array.wrap(options[:check_path]).flatten
Expand Down
4 changes: 2 additions & 2 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@

require 'url_validation'
require 'active_model'
require 'active_support/core_ext/kernel/singleton_class'
require 'active_support/core_ext'

RSpec.configure do |c|

end
68 changes: 40 additions & 28 deletions spec/url_validator_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,20 @@ class Record
@validator.validate_each(@record, :field, "")
expect(@record.errors).to be_empty
end

it "should not allow spaces" do
@validator = UrlValidator.new(:attributes => [ :field ])
@validator.validate_each(@record, :field, "http://foo bar baz")
expect(@record.errors[:field].first).to include('invalid_url')
end

it "should not allow tabs" do
@validator = UrlValidator.new(:attributes => [ :field ])
@validator.validate_each(@record, :field, "http://foo bar baz")
expect(@record.errors[:field].first).to include('invalid_url')
end
end

context "[format]" do
it "should only allow HTTP URLs if :scheme is set to 'http'" do
@validator = UrlValidator.new(:attributes => [ :field ], :scheme => 'http')
Expand All @@ -51,11 +63,11 @@ class Record
@validator.validate_each(@record, :field, "www.apple.com")
expect(@record.errors).to be_empty
end

context "[HTTP(S)]" do
it "should not allow garbage URLs that still somehow pass the ridiculously open-ended RFC" do
@validator = UrlValidator.new(:attributes => [ :field ])

[
'http:sdg.sdfg/',
'http/sdg.d',
Expand All @@ -71,7 +83,7 @@ class Record
end
end
end

context "[accessibility]" do
context "[:check_host]" do
it "should only validate if the host is accessible when :check_host is set" do
Expand Down Expand Up @@ -101,7 +113,7 @@ class Record
@validator.validate_each(@record, :field, "ftp://www.invalid.tld")
expect(@record.errors).to be_empty
end

it "should only validate if the host is accessible when :check_host is set to %w( http https ) and the URL scheme is HTTP(S)" do
@validator = UrlValidator.new(:attributes => [ :field ], :check_host => %w( http https ))
@validator.validate_each(@record, :field, "http://www.invalid.tld")
Expand All @@ -118,107 +130,107 @@ class Record
expect(@record.errors).to be_empty
end
end

context "[:check_path]" do
it "should not validate if the response code is equal to the Fixnum value of this option" do
@validator = UrlValidator.new(:attributes => [ :field ], :check_path => 404)
@validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
expect(@record.errors[:field].first).to include('url_invalid_response')

@record.errors.clear

@validator = UrlValidator.new(:attributes => [ :field ], :check_path => 405)
@validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
expect(@record.errors[:field]).to be_empty
end

it "should not validate if the response code is equal to the Symbol value of this option" do
@validator = UrlValidator.new(:attributes => [ :field ], :check_path => :not_found)
@validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
expect(@record.errors[:field].first).to include('url_invalid_response')

@record.errors.clear

@validator = UrlValidator.new(:attributes => [ :field ], :check_path => :unauthorized)
@validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
expect(@record.errors[:field]).to be_empty
end

it "should not validate if the response code is within the Range value of this option" do
@validator = UrlValidator.new(:attributes => [ :field ], :check_path => 400..499)
@validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
expect(@record.errors[:field].first).to include('url_invalid_response')

@record.errors.clear

@validator = UrlValidator.new(:attributes => [ :field ], :check_path => 500..599)
@validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
expect(@record.errors[:field]).to be_empty
end

it "should not validate if the response code is equal to the Fixnum value contained in the Array value of this option" do
@validator = UrlValidator.new(:attributes => [ :field ], :check_path => [ 404, 405 ])
@validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
expect(@record.errors[:field].first).to include('url_invalid_response')

@record.errors.clear

@validator = UrlValidator.new(:attributes => [ :field ], :check_path => [ 405, 406 ])
@validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
expect(@record.errors[:field]).to be_empty
end

it "should not validate if the response code is equal to the Symbol value contained in the Array value of this option" do
@validator = UrlValidator.new(:attributes => [ :field ], :check_path => [ :not_found, :unauthorized ])
@validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
expect(@record.errors[:field].first).to include('url_invalid_response')

@record.errors.clear

@validator = UrlValidator.new(:attributes => [ :field ], :check_path => [ :unauthorized, :moved_permanently ])
@validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
expect(@record.errors[:field]).to be_empty
end

it "should not validate if the response code is equal to the Range value contained in the Array value of this option" do
@validator = UrlValidator.new(:attributes => [ :field ], :check_path => [ 400..499, 500..599 ])
@validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
expect(@record.errors[:field].first).to include('url_invalid_response')

@record.errors.clear

@validator = UrlValidator.new(:attributes => [ :field ], :check_path => [ 500..599, 300..399 ])
@validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
expect(@record.errors[:field]).to be_empty
end

it "should skip validation by default" do
@validator = UrlValidator.new(:attributes => [ :field ], :check_path => nil)
@validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
expect(@record.errors[:field]).to be_empty
end

it "should not validate 4xx and 5xx response codes if the value is true" do
@validator = UrlValidator.new(:attributes => [ :field ], :check_path => true)
@validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
expect(@record.errors[:field].first).to include('url_invalid_response')
end

it "should skip validation for non-HTTP URLs" do
@validator = UrlValidator.new(:attributes => [ :field ], :check_path => true, :scheme => %w( ftp http https ))
@validator.validate_each(@record, :field, "ftp://ftp.sdgasdgohaodgh.com/sdgjsdg")
expect(@record.errors[:field]).to be_empty
end
end

context "[:httpi_adapter]" do
it "should use the specified HTTPI adapter" do
@validator = UrlValidator.new(:attributes => [ :field ], :httpi_adapter => :curl, :check_host => true)
expect(HTTPI).to receive(:get).once.with(an_instance_of(HTTPI::Request), :curl).and_return(false)
@validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
end
end

context "[:request_callback]" do
it "should be yielded the HTTPI request" do
called = false
Expand Down

0 comments on commit ddda6ee

Please sign in to comment.