url_validation 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
|