url_validation 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.rspec +1 -0
- data/Gemfile +13 -0
- data/Gemfile.lock +53 -0
- data/LICENSE +20 -0
- data/README.textile +36 -0
- data/Rakefile +38 -0
- data/VERSION +1 -0
- data/lib/url_validation.rb +193 -0
- data/spec/spec_helper.rb +13 -0
- data/spec/url_validator_spec.rb +231 -0
- data/url_validation.gemspec +72 -0
- metadata +153 -0
data/.document
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
-cfs
|
data/Gemfile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
source :rubygems
|
2
|
+
|
3
|
+
gem 'addressable', :require => 'addressable/uri' # for unicode URIs
|
4
|
+
gem 'activesupport'
|
5
|
+
gem 'activerecord'
|
6
|
+
gem 'httpi'
|
7
|
+
|
8
|
+
group :development do
|
9
|
+
gem 'jeweler'
|
10
|
+
gem 'yard'
|
11
|
+
gem 'RedCloth', require: 'redcloth'
|
12
|
+
gem 'rspec'
|
13
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
RedCloth (4.2.7)
|
5
|
+
activemodel (3.0.7)
|
6
|
+
activesupport (= 3.0.7)
|
7
|
+
builder (~> 2.1.2)
|
8
|
+
i18n (~> 0.5.0)
|
9
|
+
activerecord (3.0.7)
|
10
|
+
activemodel (= 3.0.7)
|
11
|
+
activesupport (= 3.0.7)
|
12
|
+
arel (~> 2.0.2)
|
13
|
+
tzinfo (~> 0.3.23)
|
14
|
+
activesupport (3.0.7)
|
15
|
+
addressable (2.2.6)
|
16
|
+
arel (2.0.10)
|
17
|
+
builder (2.1.2)
|
18
|
+
diff-lcs (1.1.2)
|
19
|
+
git (1.2.5)
|
20
|
+
httpi (0.9.4)
|
21
|
+
pyu-ntlm-http (>= 0.1.3.1)
|
22
|
+
rack
|
23
|
+
i18n (0.5.0)
|
24
|
+
jeweler (1.6.0)
|
25
|
+
bundler (~> 1.0.0)
|
26
|
+
git (>= 1.2.5)
|
27
|
+
rake
|
28
|
+
pyu-ntlm-http (0.1.3.1)
|
29
|
+
rack (1.3.0)
|
30
|
+
rake (0.9.0)
|
31
|
+
rspec (2.6.0)
|
32
|
+
rspec-core (~> 2.6.0)
|
33
|
+
rspec-expectations (~> 2.6.0)
|
34
|
+
rspec-mocks (~> 2.6.0)
|
35
|
+
rspec-core (2.6.3)
|
36
|
+
rspec-expectations (2.6.0)
|
37
|
+
diff-lcs (~> 1.1.2)
|
38
|
+
rspec-mocks (2.6.0)
|
39
|
+
tzinfo (0.3.27)
|
40
|
+
yard (0.7.1)
|
41
|
+
|
42
|
+
PLATFORMS
|
43
|
+
ruby
|
44
|
+
|
45
|
+
DEPENDENCIES
|
46
|
+
RedCloth
|
47
|
+
activerecord
|
48
|
+
activesupport
|
49
|
+
addressable
|
50
|
+
httpi
|
51
|
+
jeweler
|
52
|
+
rspec
|
53
|
+
yard
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 Tim Morgan
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.textile
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
h1. url_validation -- Simple URL validator for Rails 3
|
2
|
+
|
3
|
+
| *Author* | Tim Morgan |
|
4
|
+
| *Version* | 1.0 (May 9, 2011) |
|
5
|
+
| *License* | Released under the MIT license. |
|
6
|
+
|
7
|
+
h2. About
|
8
|
+
|
9
|
+
This gem adds a very simple URL format validator to be used with ActiveRecord
|
10
|
+
models in Rails 3.0. It supports localized error messages. It can validate many
|
11
|
+
different kinds of URLs, including HTTP and HTTPS. It supports advanced
|
12
|
+
validation features like sending @HEAD@ requests to URLS to verify that they are
|
13
|
+
valid endpoints.
|
14
|
+
|
15
|
+
h2. Installation
|
16
|
+
|
17
|
+
Add the gem to your project's @Gemfile@:
|
18
|
+
|
19
|
+
<pre><code>
|
20
|
+
gem 'url_validation'
|
21
|
+
</code></pre>
|
22
|
+
|
23
|
+
h2. Usage
|
24
|
+
|
25
|
+
This gem is an @EachValidator@, and thus is used with the @validates@ method:
|
26
|
+
|
27
|
+
<pre><code>
|
28
|
+
class User < ActiveRecord::Base
|
29
|
+
validates :terms_of_service_link,
|
30
|
+
:presence => true,
|
31
|
+
:url => true
|
32
|
+
end
|
33
|
+
</code></pre>
|
34
|
+
|
35
|
+
There are other options to fine-tune your validation; see the {UrlValidator}
|
36
|
+
class for more, and for a list of error message localization keys.
|
data/Rakefile
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
begin
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
rescue Bundler::BundlerError => e
|
6
|
+
$stderr.puts e.message
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
+
exit e.status_code
|
9
|
+
end
|
10
|
+
require 'rake'
|
11
|
+
|
12
|
+
require 'jeweler'
|
13
|
+
Jeweler::Tasks.new do |gem|
|
14
|
+
gem.name = "url_validation"
|
15
|
+
gem.summary = %Q{Simple URL validation in Rails 3}
|
16
|
+
gem.description = %Q{A simple, localizable EachValidator for URL fields in ActiveRecord 3.0.}
|
17
|
+
gem.email = "git@timothymorgan.info"
|
18
|
+
gem.homepage = "http://github.com/riscfuture/url_validation"
|
19
|
+
gem.authors = [ "Tim Morgan" ]
|
20
|
+
gem.required_ruby_version = '>= 1.8.7'
|
21
|
+
end
|
22
|
+
Jeweler::RubygemsDotOrgTasks.new
|
23
|
+
|
24
|
+
require 'yard'
|
25
|
+
YARD::Rake::YardocTask.new('doc') do |doc|
|
26
|
+
doc.options << "-m" << "textile"
|
27
|
+
doc.options << "--protected" << "--no-private"
|
28
|
+
doc.options << "-r" << "README.textile"
|
29
|
+
doc.options << "-o" << "doc"
|
30
|
+
doc.options << "--title" << "url_validation Documentation".inspect
|
31
|
+
|
32
|
+
doc.files = [ 'lib/*_validator.rb', 'README.textile' ]
|
33
|
+
end
|
34
|
+
|
35
|
+
require 'rspec/core/rake_task'
|
36
|
+
RSpec::Core::RakeTask.new
|
37
|
+
|
38
|
+
task :default => :spec
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.0.0
|
@@ -0,0 +1,193 @@
|
|
1
|
+
require 'addressable/uri'
|
2
|
+
require 'httpi'
|
3
|
+
require 'active_support/core_ext/hash/except'
|
4
|
+
require 'active_model/validator'
|
5
|
+
|
6
|
+
# Validates URLs. Uses the following I18n error message keys:
|
7
|
+
#
|
8
|
+
# | @invalid_url@ | URL is improperly formatted. |
|
9
|
+
# | @url_not_accessible@ | Couldn't connect to the URL. |
|
10
|
+
# | @url_invalid_response@ | Got a bad HTTP response (not of an acceptable type, e.g., 2xx). |
|
11
|
+
#
|
12
|
+
# @example Checks the syntax only
|
13
|
+
# validates :link, :url => true
|
14
|
+
#
|
15
|
+
# @example Ensures the host is available but does not check the path
|
16
|
+
# validates :link, :url => { :check_host => true }
|
17
|
+
#
|
18
|
+
# @example Ensures that the host is available and that a request for the path does not return a 4xx or 5xx response
|
19
|
+
# validates :link, :url => { :check_path => true }
|
20
|
+
#
|
21
|
+
# @example Ensures that the host is available and that a request for the path does not return a 3xx, 4xx, or 5xx response
|
22
|
+
# validates :link, :url => { :check_path => [ 300..399, 400..499, 500..599 ] }
|
23
|
+
#
|
24
|
+
# @example Checks for host accessibility with a custom timeout
|
25
|
+
# validates :link, :url => {
|
26
|
+
# :check_host => true,
|
27
|
+
# :request_callback => lambda { |request| request.timeout = 30 }
|
28
|
+
# }
|
29
|
+
#
|
30
|
+
# h2. Options
|
31
|
+
#
|
32
|
+
# h3. Basic options
|
33
|
+
#
|
34
|
+
# | @:allow_nil@ | If @true@, @nil@ values are allowed. |
|
35
|
+
# | @:allow_blank@ | If @true@, @nil@ or empty values are allowed. |
|
36
|
+
#
|
37
|
+
# h3. Error messages
|
38
|
+
#
|
39
|
+
# | @:invalid_url_message@ | A custom message to use in place of @:invalid_url@. |
|
40
|
+
# | @:incorrect_url_type_message@ | A custom message to use in place of @:incorrect_url_type@. |
|
41
|
+
# | @:url_not_accessible_message@ | A custom message to use in place of @:url_not_accessible@. |
|
42
|
+
# | @:url_invalid_response_message@ | A custom message to use in place of @:url_invalid_response@. |
|
43
|
+
#
|
44
|
+
# h3. Networkless URL validation
|
45
|
+
#
|
46
|
+
# | @:scheme@ | A string or array of strings, such as "http" or "ftp", indicating which URL schemes are valid. By default only ==HTTP(S)== URLs are accepted. |
|
47
|
+
# | @:default_scheme@ | A default URL scheme to try for improper URLs. If this is set to, e.g., "http", then when a URL like "whoops.com" is given (which would otherwise fail due to an improper format), "http://whoops.com" will be tried instead. |
|
48
|
+
#
|
49
|
+
# h3. Over-the-network URL validation
|
50
|
+
#
|
51
|
+
# The HTTPI gem is used to provide a generic interface to whatever HTTP client
|
52
|
+
# you wish to use. This allows you to drop in, e.g., a Curl client if you want.
|
53
|
+
# You can set the HTTPI adapter with the @:httpi_adapter@ option.
|
54
|
+
#
|
55
|
+
# | @:check_host@ | If @true@, the validator will perform a network test to verify that it can connect to the server and access the host (at the "/" path). This check will only be performed for ==HTTP(S)== URLs. |
|
56
|
+
# | @:check_path@ | An integer or symbol (or array of integers or symbols), such as 301 or @:moved_permanently@, indicating what response codes are unacceptable. You can also use ranges, and include them in an array, such as @[ :moved_permanently, 400..404, 500..599 ]@. By default, this is @nil@, and therefore only host accessibility is checked. If @true@ is given, uses a default set of invalid error codes (4xx and 5xx). Implies @:check_host@ is also true. |
|
57
|
+
# | @:httpi_adapter@ | The HTTPI adapter to use for checking HTTP and HTTPS URLs (default set by the HTTPI gem). |
|
58
|
+
#
|
59
|
+
# h3. Other options
|
60
|
+
#
|
61
|
+
# | @: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. |
|
62
|
+
|
63
|
+
class UrlValidator < ActiveModel::EachValidator
|
64
|
+
# @private
|
65
|
+
CODES = {
|
66
|
+
:continue => 100,
|
67
|
+
:switching_protocols => 101,
|
68
|
+
:processing => 102,
|
69
|
+
:ok => 200,
|
70
|
+
:created => 201,
|
71
|
+
:accepted => 202,
|
72
|
+
:non_authoritative_information => 203,
|
73
|
+
:no_content => 204,
|
74
|
+
:reset_content => 205,
|
75
|
+
:partial_content => 206,
|
76
|
+
:multi_status => 207,
|
77
|
+
:im_used => 226,
|
78
|
+
:multiple_choices => 300,
|
79
|
+
:moved_permanently => 301,
|
80
|
+
:found => 302,
|
81
|
+
:see_other => 303,
|
82
|
+
:not_modified => 304,
|
83
|
+
:use_proxy => 305,
|
84
|
+
:reserved => 306,
|
85
|
+
:temporary_redirect => 307,
|
86
|
+
:bad_request => 400,
|
87
|
+
:unauthorized => 401,
|
88
|
+
:payment_required => 402,
|
89
|
+
:forbidden => 403,
|
90
|
+
:not_found => 404,
|
91
|
+
:method_not_allowed => 405,
|
92
|
+
:not_acceptable => 406,
|
93
|
+
:proxy_authentication_required => 407,
|
94
|
+
:request_timeout => 408,
|
95
|
+
:conflict => 409,
|
96
|
+
:gone => 410,
|
97
|
+
:length_required => 411,
|
98
|
+
:precondition_failed => 412,
|
99
|
+
:request_entity_too_large => 413,
|
100
|
+
:request_uri_too_long => 414,
|
101
|
+
:unsupported_media_type => 415,
|
102
|
+
:requested_range_not_satisfiable => 416,
|
103
|
+
:expectation_failed => 417,
|
104
|
+
:unprocessable_entity => 422,
|
105
|
+
:locked => 423,
|
106
|
+
:failed_dependency => 424,
|
107
|
+
:upgrade_required => 426,
|
108
|
+
:internal_server_error => 500,
|
109
|
+
:not_implemented => 501,
|
110
|
+
:bad_gateway => 502,
|
111
|
+
:service_unavailable => 503,
|
112
|
+
:gateway_timeout => 504,
|
113
|
+
:http_version_not_supported => 505,
|
114
|
+
:variant_also_negotiates => 506,
|
115
|
+
:insufficient_storage => 507,
|
116
|
+
:not_extended => 510
|
117
|
+
}
|
118
|
+
|
119
|
+
|
120
|
+
# @private
|
121
|
+
def validate_each(record, attribute, value)
|
122
|
+
return if options[:allow_nil] and value.nil?
|
123
|
+
return if options[:allow_blank] and value.blank?
|
124
|
+
|
125
|
+
uri = Addressable::URI.parse(value)
|
126
|
+
if uri.scheme.nil? and options[:default_scheme] then
|
127
|
+
uri = Addressable::URI.parse("#{options[:default_scheme]}://#{value}")
|
128
|
+
end
|
129
|
+
|
130
|
+
record.errors.add(attribute, options[:invalid_url_message] || :invalid_url) unless url_format_valid?(uri, options)
|
131
|
+
record.errors.add(attribute, options[:url_not_accessible_message] || :url_not_accessible) unless response = url_accessible?(uri, options)
|
132
|
+
record.errors.add(attribute, options[:url_invalid_response_message] || :url_invalid_response) unless url_response_valid?(response, options)
|
133
|
+
end
|
134
|
+
|
135
|
+
private
|
136
|
+
|
137
|
+
def url_format_valid?(uri, options)
|
138
|
+
return false unless Array.wrap(options[:scheme] || %w( http https )).include?(uri.scheme)
|
139
|
+
|
140
|
+
case uri.scheme
|
141
|
+
when 'http', 'https'
|
142
|
+
return http_url_format_valid?(uri)
|
143
|
+
else
|
144
|
+
return true
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def http_url_format_valid?(uri)
|
149
|
+
uri.host.present? and not uri.path.nil?
|
150
|
+
end
|
151
|
+
|
152
|
+
def url_accessible?(uri, options)
|
153
|
+
return true unless options[:check_host] or options[:check_path]
|
154
|
+
|
155
|
+
check_host = options[:check_host]
|
156
|
+
check_host ||= %w( http https ) if options[:check_path]
|
157
|
+
if (schemes = Array.wrap(check_host)) and schemes.all? { |scheme| scheme.kind_of?(String) } then
|
158
|
+
return true unless schemes.include?(uri.scheme)
|
159
|
+
end
|
160
|
+
|
161
|
+
case uri.scheme
|
162
|
+
when 'http', 'https'
|
163
|
+
return http_url_accessible?(uri, options)
|
164
|
+
else
|
165
|
+
return true
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
def http_url_accessible?(uri, options)
|
170
|
+
request = HTTPI::Request.new(uri.to_s)
|
171
|
+
options[:request_callback].call(request) if options[:request_callback].respond_to?(:call)
|
172
|
+
return HTTPI.get(request, options[:httpi_adapter])
|
173
|
+
rescue
|
174
|
+
return false
|
175
|
+
end
|
176
|
+
|
177
|
+
def url_response_valid?(response, options)
|
178
|
+
return true unless response.kind_of?(HTTPI::Response) and options[:check_path]
|
179
|
+
response_codes = options[:check_path] == true ? [400..499, 500..599] : Array.wrap(options[:check_path]).flatten
|
180
|
+
return response_codes.none? do |code| # it's good if it's not a bad response
|
181
|
+
case code # and it's a bad response if...
|
182
|
+
when Range
|
183
|
+
code.include? response.code
|
184
|
+
when Fixnum
|
185
|
+
code == response.code
|
186
|
+
when Symbol
|
187
|
+
CODES.include?(code) && CODES[code] == response.code
|
188
|
+
else # be generous and treat it as a non-match if we don't know what it is
|
189
|
+
false
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler.require :default, :development
|
3
|
+
|
4
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
5
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
6
|
+
|
7
|
+
require 'url_validation'
|
8
|
+
require 'active_model'
|
9
|
+
require 'active_support/core_ext/kernel/singleton_class'
|
10
|
+
|
11
|
+
RSpec.configure do |c|
|
12
|
+
|
13
|
+
end
|
@@ -0,0 +1,231 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class Record
|
4
|
+
extend ActiveModel::Translation
|
5
|
+
include ActiveModel::Validations
|
6
|
+
attr_accessor :field
|
7
|
+
end
|
8
|
+
|
9
|
+
describe UrlValidator do
|
10
|
+
before :each do
|
11
|
+
@record = Record.new
|
12
|
+
end
|
13
|
+
|
14
|
+
context "[basic]" do
|
15
|
+
it "should allow nil if :allow_nil is set" do
|
16
|
+
@validator = UrlValidator.new(:attributes => [ :field ], :allow_nil => true)
|
17
|
+
@validator.validate_each(@record, :field, nil)
|
18
|
+
@record.errors.should be_empty
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should allow \"\" if :allow_blank is set" do
|
22
|
+
@validator = UrlValidator.new(:attributes => [ :field ], :allow_blank => true)
|
23
|
+
@validator.validate_each(@record, :field, "")
|
24
|
+
@record.errors.should be_empty
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context "[format]" do
|
29
|
+
it "should only allow HTTP URLs if :scheme is set to 'http'" do
|
30
|
+
@validator = UrlValidator.new(:attributes => [ :field ], :scheme => 'http')
|
31
|
+
@validator.validate_each(@record, :field, "http://www.apple.com")
|
32
|
+
@record.errors.should be_empty
|
33
|
+
|
34
|
+
@validator.validate_each(@record, :field, "https://www.apple.com")
|
35
|
+
@record.errors[:field].first.should include('invalid_url')
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should only allow HTTP and HTTPS URLs if :scheme is set to %w( http https )" do
|
39
|
+
@validator = UrlValidator.new(:attributes => [ :field ], :scheme => %w( http https ))
|
40
|
+
@validator.validate_each(@record, :field, "http://www.apple.com")
|
41
|
+
@record.errors.should be_empty
|
42
|
+
@validator.validate_each(@record, :field, "https://www.apple.com")
|
43
|
+
@record.errors.should be_empty
|
44
|
+
|
45
|
+
@validator.validate_each(@record, :field, "ftp://www.apple.com")
|
46
|
+
@record.errors[:field].first.should include('invalid_url')
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should try a default scheme if :default_scheme is set" do
|
50
|
+
@validator = UrlValidator.new(:attributes => [ :field ], :scheme => 'http', :default_scheme => 'http')
|
51
|
+
@validator.validate_each(@record, :field, "www.apple.com")
|
52
|
+
@record.errors.should be_empty
|
53
|
+
end
|
54
|
+
|
55
|
+
context "[HTTP(S)]" do
|
56
|
+
it "should not allow garbage URLs that still somehow pass the ridiculously open-ended RFC" do
|
57
|
+
@validator = UrlValidator.new(:attributes => [ :field ])
|
58
|
+
|
59
|
+
[
|
60
|
+
'http:sdg.sdfg/',
|
61
|
+
'http/sdg.d',
|
62
|
+
'http:://dsfg.dsfg/',
|
63
|
+
'http//sdg..g',
|
64
|
+
'http://://sdfg.f',
|
65
|
+
'http://dsaf.com://sdg.com'
|
66
|
+
].each do |uri|
|
67
|
+
@record.errors.clear
|
68
|
+
@validator.validate_each(@record, :field, "www.apple.com")
|
69
|
+
@record.errors[:field].first.should include('invalid_url')
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
context "[accessibility]" do
|
76
|
+
context "[:check_host]" do
|
77
|
+
it "should only validate if the host is accessible when :check_host is set" do
|
78
|
+
@validator = UrlValidator.new(:attributes => [ :field ])
|
79
|
+
@validator.validate_each(@record, :field, "http://www.invalid.tld")
|
80
|
+
@record.errors.should be_empty
|
81
|
+
|
82
|
+
@validator = UrlValidator.new(:attributes => [ :field ], :check_host => true)
|
83
|
+
@validator.validate_each(@record, :field, "http://www.invalid.tld")
|
84
|
+
@record.errors[:field].first.should include('url_not_accessible')
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should not perform the accessibility check if :check_host is set to 'http' and the URL scheme is not HTTP" do
|
88
|
+
@validator = UrlValidator.new(:attributes => [ :field ], :check_host => 'http')
|
89
|
+
@validator.validate_each(@record, :field, "https://www.invalid.tld")
|
90
|
+
@record.errors.should be_empty
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should only validate if the host is accessible when :check_host is set to 'http' and the URL scheme is HTTP" do
|
94
|
+
@validator = UrlValidator.new(:attributes => [ :field ], :check_host => 'http')
|
95
|
+
@validator.validate_each(@record, :field, "http://www.invalid.tld")
|
96
|
+
@record.errors[:field].first.should include('url_not_accessible')
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should not perform the accessibility check if :check_host is set to %w( http https ) and the URL scheme is not HTTP(S)" do
|
100
|
+
@validator = UrlValidator.new(:attributes => [ :field ], :check_host => %w( http https ), :scheme => %w( ftp http https ))
|
101
|
+
@validator.validate_each(@record, :field, "ftp://www.invalid.tld")
|
102
|
+
@record.errors.should be_empty
|
103
|
+
end
|
104
|
+
|
105
|
+
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
|
106
|
+
@validator = UrlValidator.new(:attributes => [ :field ], :check_host => %w( http https ))
|
107
|
+
@validator.validate_each(@record, :field, "http://www.invalid.tld")
|
108
|
+
@record.errors[:field].first.should include('url_not_accessible')
|
109
|
+
|
110
|
+
@validator = UrlValidator.new(:attributes => [ :field ], :check_host => %w( http https ))
|
111
|
+
@validator.validate_each(@record, :field, "https://www.invalid.tld")
|
112
|
+
@record.errors[:field].first.should include('url_not_accessible')
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should only validate the host" do
|
116
|
+
@validator = UrlValidator.new(:attributes => [ :field ], :check_host => true)
|
117
|
+
@validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
|
118
|
+
@record.errors.should be_empty
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
context "[:check_path]" do
|
123
|
+
it "should not validate if the response code is equal to the Fixnum value of this option" do
|
124
|
+
@validator = UrlValidator.new(:attributes => [ :field ], :check_path => 404)
|
125
|
+
@validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
|
126
|
+
@record.errors[:field].first.should include('url_invalid_response')
|
127
|
+
|
128
|
+
@record.errors.clear
|
129
|
+
|
130
|
+
@validator = UrlValidator.new(:attributes => [ :field ], :check_path => 405)
|
131
|
+
@validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
|
132
|
+
@record.errors[:field].should be_empty
|
133
|
+
end
|
134
|
+
|
135
|
+
it "should not validate if the response code is equal to the Symbol value of this option" do
|
136
|
+
@validator = UrlValidator.new(:attributes => [ :field ], :check_path => :not_found)
|
137
|
+
@validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
|
138
|
+
@record.errors[:field].first.should include('url_invalid_response')
|
139
|
+
|
140
|
+
@record.errors.clear
|
141
|
+
|
142
|
+
@validator = UrlValidator.new(:attributes => [ :field ], :check_path => :unauthorized)
|
143
|
+
@validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
|
144
|
+
@record.errors[:field].should be_empty
|
145
|
+
end
|
146
|
+
|
147
|
+
it "should not validate if the response code is within the Range value of this option" do
|
148
|
+
@validator = UrlValidator.new(:attributes => [ :field ], :check_path => 400..499)
|
149
|
+
@validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
|
150
|
+
@record.errors[:field].first.should include('url_invalid_response')
|
151
|
+
|
152
|
+
@record.errors.clear
|
153
|
+
|
154
|
+
@validator = UrlValidator.new(:attributes => [ :field ], :check_path => 500..599)
|
155
|
+
@validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
|
156
|
+
@record.errors[:field].should be_empty
|
157
|
+
end
|
158
|
+
|
159
|
+
it "should not validate if the response code is equal to the Fixnum value contained in the Array value of this option" do
|
160
|
+
@validator = UrlValidator.new(:attributes => [ :field ], :check_path => [ 404, 405 ])
|
161
|
+
@validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
|
162
|
+
@record.errors[:field].first.should include('url_invalid_response')
|
163
|
+
|
164
|
+
@record.errors.clear
|
165
|
+
|
166
|
+
@validator = UrlValidator.new(:attributes => [ :field ], :check_path => [ 405, 406 ])
|
167
|
+
@validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
|
168
|
+
@record.errors[:field].should be_empty
|
169
|
+
end
|
170
|
+
|
171
|
+
it "should not validate if the response code is equal to the Symbol value contained in the Array value of this option" do
|
172
|
+
@validator = UrlValidator.new(:attributes => [ :field ], :check_path => [ :not_found, :unauthorized ])
|
173
|
+
@validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
|
174
|
+
@record.errors[:field].first.should include('url_invalid_response')
|
175
|
+
|
176
|
+
@record.errors.clear
|
177
|
+
|
178
|
+
@validator = UrlValidator.new(:attributes => [ :field ], :check_path => [ :unauthorized, :moved_permanently ])
|
179
|
+
@validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
|
180
|
+
@record.errors[:field].should be_empty
|
181
|
+
end
|
182
|
+
|
183
|
+
it "should not validate if the response code is equal to the Range value contained in the Array value of this option" do
|
184
|
+
@validator = UrlValidator.new(:attributes => [ :field ], :check_path => [ 400..499, 500..599 ])
|
185
|
+
@validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
|
186
|
+
@record.errors[:field].first.should include('url_invalid_response')
|
187
|
+
|
188
|
+
@record.errors.clear
|
189
|
+
|
190
|
+
@validator = UrlValidator.new(:attributes => [ :field ], :check_path => [ 500..599, 300..399 ])
|
191
|
+
@validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
|
192
|
+
@record.errors[:field].should be_empty
|
193
|
+
end
|
194
|
+
|
195
|
+
it "should skip validation by default" do
|
196
|
+
@validator = UrlValidator.new(:attributes => [ :field ], :check_path => nil)
|
197
|
+
@validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
|
198
|
+
@record.errors[:field].should be_empty
|
199
|
+
end
|
200
|
+
|
201
|
+
it "should not validate 4xx and 5xx response codes if the value is true" do
|
202
|
+
@validator = UrlValidator.new(:attributes => [ :field ], :check_path => true)
|
203
|
+
@validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
|
204
|
+
@record.errors[:field].first.should include('url_invalid_response')
|
205
|
+
end
|
206
|
+
|
207
|
+
it "should skip validation for non-HTTP URLs" do
|
208
|
+
@validator = UrlValidator.new(:attributes => [ :field ], :check_path => true, :scheme => %w( ftp http https ))
|
209
|
+
@validator.validate_each(@record, :field, "ftp://ftp.sdgasdgohaodgh.com/sdgjsdg")
|
210
|
+
@record.errors[:field].should be_empty
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
context "[:httpi_adapter]" do
|
215
|
+
it "should use the specified HTTPI adapter" do
|
216
|
+
@validator = UrlValidator.new(:attributes => [ :field ], :httpi_adapter => :curl, :check_host => true)
|
217
|
+
HTTPI.should_receive(:get).once.with(an_instance_of(HTTPI::Request), :curl).and_return(false)
|
218
|
+
@validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
context "[:request_callback]" do
|
223
|
+
it "should be yielded the HTTPI request" do
|
224
|
+
called = false
|
225
|
+
@validator = UrlValidator.new(:attributes => [ :field ], :check_host => true, :request_callback => lambda { |request| called = true; request.should be_kind_of(HTTPI::Request) })
|
226
|
+
@validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
|
227
|
+
called.should be_true
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{url_validation}
|
8
|
+
s.version = "1.0.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = [%q{Tim Morgan}]
|
12
|
+
s.date = %q{2011-05-27}
|
13
|
+
s.description = %q{A simple, localizable EachValidator for URL fields in ActiveRecord 3.0.}
|
14
|
+
s.email = %q{git@timothymorgan.info}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.textile"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".document",
|
21
|
+
".rspec",
|
22
|
+
"Gemfile",
|
23
|
+
"Gemfile.lock",
|
24
|
+
"LICENSE",
|
25
|
+
"README.textile",
|
26
|
+
"Rakefile",
|
27
|
+
"VERSION",
|
28
|
+
"lib/url_validation.rb",
|
29
|
+
"spec/spec_helper.rb",
|
30
|
+
"spec/url_validator_spec.rb",
|
31
|
+
"url_validation.gemspec"
|
32
|
+
]
|
33
|
+
s.homepage = %q{http://github.com/riscfuture/url_validation}
|
34
|
+
s.require_paths = [%q{lib}]
|
35
|
+
s.required_ruby_version = Gem::Requirement.new(">= 1.8.7")
|
36
|
+
s.rubygems_version = %q{1.8.3}
|
37
|
+
s.summary = %q{Simple URL validation in Rails 3}
|
38
|
+
|
39
|
+
if s.respond_to? :specification_version then
|
40
|
+
s.specification_version = 3
|
41
|
+
|
42
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
43
|
+
s.add_runtime_dependency(%q<addressable>, [">= 0"])
|
44
|
+
s.add_runtime_dependency(%q<activesupport>, [">= 0"])
|
45
|
+
s.add_runtime_dependency(%q<activerecord>, [">= 0"])
|
46
|
+
s.add_runtime_dependency(%q<httpi>, [">= 0"])
|
47
|
+
s.add_development_dependency(%q<jeweler>, [">= 0"])
|
48
|
+
s.add_development_dependency(%q<yard>, [">= 0"])
|
49
|
+
s.add_development_dependency(%q<RedCloth>, [">= 0"])
|
50
|
+
s.add_development_dependency(%q<rspec>, [">= 0"])
|
51
|
+
else
|
52
|
+
s.add_dependency(%q<addressable>, [">= 0"])
|
53
|
+
s.add_dependency(%q<activesupport>, [">= 0"])
|
54
|
+
s.add_dependency(%q<activerecord>, [">= 0"])
|
55
|
+
s.add_dependency(%q<httpi>, [">= 0"])
|
56
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
57
|
+
s.add_dependency(%q<yard>, [">= 0"])
|
58
|
+
s.add_dependency(%q<RedCloth>, [">= 0"])
|
59
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
60
|
+
end
|
61
|
+
else
|
62
|
+
s.add_dependency(%q<addressable>, [">= 0"])
|
63
|
+
s.add_dependency(%q<activesupport>, [">= 0"])
|
64
|
+
s.add_dependency(%q<activerecord>, [">= 0"])
|
65
|
+
s.add_dependency(%q<httpi>, [">= 0"])
|
66
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
67
|
+
s.add_dependency(%q<yard>, [">= 0"])
|
68
|
+
s.add_dependency(%q<RedCloth>, [">= 0"])
|
69
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
metadata
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: url_validation
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 1.0.0
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Tim Morgan
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-05-27 00:00:00 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: addressable
|
17
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: "0"
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: *id001
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: activesupport
|
28
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
29
|
+
none: false
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: "0"
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: *id002
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: activerecord
|
39
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: "0"
|
45
|
+
type: :runtime
|
46
|
+
prerelease: false
|
47
|
+
version_requirements: *id003
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: httpi
|
50
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: "0"
|
56
|
+
type: :runtime
|
57
|
+
prerelease: false
|
58
|
+
version_requirements: *id004
|
59
|
+
- !ruby/object:Gem::Dependency
|
60
|
+
name: jeweler
|
61
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
63
|
+
requirements:
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: "0"
|
67
|
+
type: :development
|
68
|
+
prerelease: false
|
69
|
+
version_requirements: *id005
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: yard
|
72
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: "0"
|
78
|
+
type: :development
|
79
|
+
prerelease: false
|
80
|
+
version_requirements: *id006
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
name: RedCloth
|
83
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
84
|
+
none: false
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: "0"
|
89
|
+
type: :development
|
90
|
+
prerelease: false
|
91
|
+
version_requirements: *id007
|
92
|
+
- !ruby/object:Gem::Dependency
|
93
|
+
name: rspec
|
94
|
+
requirement: &id008 !ruby/object:Gem::Requirement
|
95
|
+
none: false
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: "0"
|
100
|
+
type: :development
|
101
|
+
prerelease: false
|
102
|
+
version_requirements: *id008
|
103
|
+
description: A simple, localizable EachValidator for URL fields in ActiveRecord 3.0.
|
104
|
+
email: git@timothymorgan.info
|
105
|
+
executables: []
|
106
|
+
|
107
|
+
extensions: []
|
108
|
+
|
109
|
+
extra_rdoc_files:
|
110
|
+
- LICENSE
|
111
|
+
- README.textile
|
112
|
+
files:
|
113
|
+
- .document
|
114
|
+
- .rspec
|
115
|
+
- Gemfile
|
116
|
+
- Gemfile.lock
|
117
|
+
- LICENSE
|
118
|
+
- README.textile
|
119
|
+
- Rakefile
|
120
|
+
- VERSION
|
121
|
+
- lib/url_validation.rb
|
122
|
+
- spec/spec_helper.rb
|
123
|
+
- spec/url_validator_spec.rb
|
124
|
+
- url_validation.gemspec
|
125
|
+
homepage: http://github.com/riscfuture/url_validation
|
126
|
+
licenses: []
|
127
|
+
|
128
|
+
post_install_message:
|
129
|
+
rdoc_options: []
|
130
|
+
|
131
|
+
require_paths:
|
132
|
+
- lib
|
133
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
134
|
+
none: false
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: 1.8.7
|
139
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
140
|
+
none: false
|
141
|
+
requirements:
|
142
|
+
- - ">="
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: "0"
|
145
|
+
requirements: []
|
146
|
+
|
147
|
+
rubyforge_project:
|
148
|
+
rubygems_version: 1.8.3
|
149
|
+
signing_key:
|
150
|
+
specification_version: 3
|
151
|
+
summary: Simple URL validation in Rails 3
|
152
|
+
test_files: []
|
153
|
+
|