url_validation 1.2.0 → 2.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.
- checksums.yaml +5 -5
- data/CHANGELOG.md +52 -0
- data/README.md +121 -18
- data/Rakefile +4 -34
- data/lib/url_validation/version.rb +9 -0
- data/lib/url_validation.rb +39 -22
- data/url_validation.gemspec +43 -69
- metadata +55 -60
- data/.document +0 -5
- data/.rspec +0 -2
- data/.ruby-gemset +0 -1
- data/.ruby-version +0 -1
- data/Gemfile +0 -18
- data/Gemfile.lock +0 -106
- data/VERSION +0 -1
- data/spec/spec_helper.rb +0 -13
- data/spec/url_validator_spec.rb +0 -235
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 3060391d73d4937f667c371401a15591f538001c9db4c9e60457646b31625ffb
|
|
4
|
+
data.tar.gz: 3450f357cf02db8279a324e369beeb69eeb1842242d2ff6cc59102fdd1006ad3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7111f507cf4f8f06f1e8c182846aed69633e404d0b4f5a1530ee2822ec165714de37850a243dc0b9616d262dc389c44bed9beba9c34b8e2a57f7cb84b0f0e97d
|
|
7
|
+
data.tar.gz: 5e58055eadde1913e32045b4f4f52efc838dbb6c88affafcba75c541b032dfc7c8635cbcca90c8201854f228f401c567428f65ab38c9f53b4ee6eac73f154721
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [2.0.0] - 2026-05-14
|
|
9
|
+
|
|
10
|
+
### Breaking
|
|
11
|
+
|
|
12
|
+
- Drops the runtime dependency on `activerecord`. The gem only ever needed
|
|
13
|
+
`ActiveModel::EachValidator`, so it now depends on `activemodel` (and
|
|
14
|
+
`activesupport`) directly. Apps that pulled `activerecord` in transitively
|
|
15
|
+
through this gem will need to declare it themselves if required.
|
|
16
|
+
- Bumps `required_ruby_version` to `>= 3.1`.
|
|
17
|
+
- Bumps `activemodel` / `activesupport` minimum to `>= 6.1`.
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
|
|
21
|
+
- New `:http_method` option (default `:head`) lets callers choose the HTTP
|
|
22
|
+
verb used for accessibility checks. Useful for servers that do not handle
|
|
23
|
+
`HEAD` correctly.
|
|
24
|
+
- `webmock` is wired into the spec suite and `WebMock.disable_net_connect!`
|
|
25
|
+
is enabled, so the test suite no longer makes live network calls.
|
|
26
|
+
- GitHub Actions workflow tests Ruby 3.1-3.4 against ActiveModel 7.0-8.0.
|
|
27
|
+
- `bin/console`, `bin/setup`, modern `Rakefile`, hand-written gemspec.
|
|
28
|
+
- `CHANGELOG.md`.
|
|
29
|
+
|
|
30
|
+
### Fixed
|
|
31
|
+
|
|
32
|
+
- **Accessibility check now uses `HEAD` requests, as documented.** Previously
|
|
33
|
+
the code called `HTTPI.get`, contradicting the README. It now calls
|
|
34
|
+
`HTTPI.request(:head, ...)` by default.
|
|
35
|
+
- **`allow_blank: false` is now honored.** Previously the validator's
|
|
36
|
+
`return if value.blank?` short-circuit overrode an explicit
|
|
37
|
+
`allow_blank: false` option. Blank values now flow through to
|
|
38
|
+
format validation when `allow_blank` is false.
|
|
39
|
+
- **Rescue branch no longer references a re-parsed URI.** When the
|
|
40
|
+
`default_scheme` re-parse raised, the rescue branch could call
|
|
41
|
+
`url_format_valid?` against a previously-set URI in an inconsistent
|
|
42
|
+
state. The rescue branch now adds `:invalid_url` unconditionally and
|
|
43
|
+
returns, which matches the documented behavior.
|
|
44
|
+
|
|
45
|
+
### Removed
|
|
46
|
+
|
|
47
|
+
- `.travis.yml`, juwelier-generated gemspec, `VERSION` text file.
|
|
48
|
+
- Runtime `activerecord` dependency.
|
|
49
|
+
|
|
50
|
+
## [1.2.0]
|
|
51
|
+
|
|
52
|
+
- Last juwelier-managed release.
|
data/README.md
CHANGED
|
@@ -1,40 +1,143 @@
|
|
|
1
1
|
# url_validation
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://github.com/RISCfuture/url_validation/actions/workflows/ci.yml)
|
|
4
|
+
[](https://rubygems.org/gems/url_validation)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
|
|
7
|
+
A simple, localizable `ActiveModel::EachValidator` for URL fields.
|
|
4
8
|
|
|
5
9
|
| | |
|
|
6
10
|
|:------------|:--------------------------------|
|
|
7
11
|
| **Author** | Tim Morgan |
|
|
8
|
-
| **Version** | 1.0 (May 9, 2011) |
|
|
9
12
|
| **License** | Released under the MIT license. |
|
|
10
13
|
|
|
11
14
|
## About
|
|
12
15
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
validation features like sending `HEAD` requests to URLS to verify that they are
|
|
17
|
-
valid endpoints.
|
|
16
|
+
`url_validation` adds a URL validator usable in any `ActiveModel` (or `ActiveRecord`)
|
|
17
|
+
class. It supports localized error messages, multiple schemes, and optional
|
|
18
|
+
over-the-network reachability checks (`HEAD` by default, configurable).
|
|
18
19
|
|
|
19
20
|
## Installation
|
|
20
21
|
|
|
21
|
-
Add
|
|
22
|
+
Add to your `Gemfile`:
|
|
22
23
|
|
|
23
|
-
```
|
|
24
|
-
gem
|
|
24
|
+
```ruby
|
|
25
|
+
gem "url_validation"
|
|
25
26
|
```
|
|
26
27
|
|
|
28
|
+
Then `bundle install`.
|
|
29
|
+
|
|
30
|
+
This gem depends on `activemodel >= 6.1`. It does not require `activerecord`.
|
|
31
|
+
|
|
27
32
|
## Usage
|
|
28
33
|
|
|
29
|
-
|
|
34
|
+
It's an `EachValidator`, so use it with `validates`:
|
|
30
35
|
|
|
31
|
-
```
|
|
32
|
-
class User
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
+
```ruby
|
|
37
|
+
class User
|
|
38
|
+
include ActiveModel::Model
|
|
39
|
+
include ActiveModel::Validations
|
|
40
|
+
|
|
41
|
+
attr_accessor :terms_of_service_link
|
|
42
|
+
validates :terms_of_service_link, presence: true, url: true
|
|
36
43
|
end
|
|
37
44
|
```
|
|
38
45
|
|
|
39
|
-
|
|
40
|
-
|
|
46
|
+
### Examples
|
|
47
|
+
|
|
48
|
+
```ruby
|
|
49
|
+
# Format only (no network)
|
|
50
|
+
validates :link, url: true
|
|
51
|
+
|
|
52
|
+
# Restrict to a specific scheme (or list)
|
|
53
|
+
validates :link, url: {scheme: "https"}
|
|
54
|
+
validates :link, url: {scheme: %w[http https ftp]}
|
|
55
|
+
|
|
56
|
+
# If the user types "example.com", treat it as "http://example.com"
|
|
57
|
+
validates :link, url: {default_scheme: "http"}
|
|
58
|
+
|
|
59
|
+
# Verify host is reachable (sends a HEAD request)
|
|
60
|
+
validates :link, url: {check_host: true}
|
|
61
|
+
|
|
62
|
+
# Verify the path resolves to something other than 4xx/5xx
|
|
63
|
+
validates :link, url: {check_path: true}
|
|
64
|
+
validates :link, url: {check_path: [300..399, 400..499, 500..599]}
|
|
65
|
+
|
|
66
|
+
# Use GET instead of HEAD (for servers that don't handle HEAD properly)
|
|
67
|
+
validates :link, url: {check_host: true, http_method: :get}
|
|
68
|
+
|
|
69
|
+
# Customize the HTTPI request (timeouts, headers, etc.)
|
|
70
|
+
validates :link, url: {
|
|
71
|
+
check_host: true,
|
|
72
|
+
request_callback: ->(request) { request.open_timeout = 5; request.read_timeout = 5 }
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Options
|
|
77
|
+
|
|
78
|
+
### Basic
|
|
79
|
+
|
|
80
|
+
| Option | Description |
|
|
81
|
+
|:---------------|:-------------------------------------------------------------------------|
|
|
82
|
+
| `:allow_nil` | If `true`, `nil` values are allowed. |
|
|
83
|
+
| `:allow_blank` | If `true` (the default), `nil` or empty values are allowed without running format checks. Set to `false` to flag blank values as `:invalid_url`. |
|
|
84
|
+
|
|
85
|
+
### Error messages
|
|
86
|
+
|
|
87
|
+
Override the I18n key the validator uses when adding errors:
|
|
88
|
+
|
|
89
|
+
| Option | Replaces I18n key |
|
|
90
|
+
|:--------------------------------|:------------------------|
|
|
91
|
+
| `:invalid_url_message` | `:invalid_url` |
|
|
92
|
+
| `:url_not_accessible_message` | `:url_not_accessible` |
|
|
93
|
+
| `:url_invalid_response_message` | `:url_invalid_response` |
|
|
94
|
+
|
|
95
|
+
### Format checks (no network)
|
|
96
|
+
|
|
97
|
+
| Option | Description |
|
|
98
|
+
|:------------------|:-------------------------------------------------------------------------------------------------------------------------------------|
|
|
99
|
+
| `:scheme` | A string or array of strings indicating acceptable URL schemes. Defaults to `%w[http https]`. |
|
|
100
|
+
| `:default_scheme` | If set (e.g., `"http"`), a URL without a scheme will have this scheme prepended before validation, so `"example.com"` parses fine. |
|
|
101
|
+
|
|
102
|
+
### Network checks
|
|
103
|
+
|
|
104
|
+
`url_validation` uses [HTTPI](https://rubygems.org/gems/httpi) to issue requests,
|
|
105
|
+
so you can pick your underlying HTTP client.
|
|
106
|
+
|
|
107
|
+
| Option | Description |
|
|
108
|
+
|:------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
109
|
+
| `:check_host` | If `true`, perform a request to the host to verify connectivity. Only runs for HTTP(S) URLs unless overridden. |
|
|
110
|
+
| `:check_path` | Treat specific response codes as invalid. Pass an Integer, a Symbol (e.g. `:not_found`), a Range (`400..499`), or an Array of these. `true` means "4xx or 5xx is invalid." Implies `:check_host`. |
|
|
111
|
+
| `:httpi_adapter` | The HTTPI adapter to use (default: HTTPI's default). |
|
|
112
|
+
| `:http_method` | The HTTP verb used for the accessibility check, as a Symbol. Defaults to `:head`. Use `:get` for servers that mis-handle `HEAD`. |
|
|
113
|
+
| `:request_callback` | A `Proc`/lambda invoked with the `HTTPI::Request` before it executes. Use for custom timeouts, headers, auth, etc. |
|
|
114
|
+
|
|
115
|
+
## Localization
|
|
116
|
+
|
|
117
|
+
The validator emits the standard ActiveModel error symbols (`:invalid_url`,
|
|
118
|
+
`:url_not_accessible`, `:url_invalid_response`). Provide translations under the
|
|
119
|
+
usual `activemodel.errors.messages` namespace (or use the `Model.errors.messages`
|
|
120
|
+
fallback). Example `config/locales/en.yml`:
|
|
121
|
+
|
|
122
|
+
```yaml
|
|
123
|
+
en:
|
|
124
|
+
errors:
|
|
125
|
+
messages:
|
|
126
|
+
invalid_url: "is not a valid URL"
|
|
127
|
+
url_not_accessible: "is not reachable"
|
|
128
|
+
url_invalid_response: "returned a bad response"
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Development
|
|
132
|
+
|
|
133
|
+
```sh
|
|
134
|
+
bin/setup
|
|
135
|
+
bundle exec rspec
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
The spec suite uses [webmock](https://rubygems.org/gems/webmock) with
|
|
139
|
+
`disable_net_connect!`, so tests never touch the network.
|
|
140
|
+
|
|
141
|
+
## License
|
|
142
|
+
|
|
143
|
+
MIT. See `LICENSE`.
|
data/Rakefile
CHANGED
|
@@ -1,38 +1,8 @@
|
|
|
1
|
-
|
|
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'
|
|
1
|
+
# frozen_string_literal: true
|
|
11
2
|
|
|
12
|
-
require
|
|
13
|
-
|
|
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 = '>= 2.0.0'
|
|
21
|
-
end
|
|
22
|
-
Juwelier::RubygemsDotOrgTasks.new
|
|
3
|
+
require "bundler/gem_tasks"
|
|
4
|
+
require "rspec/core/rake_task"
|
|
23
5
|
|
|
24
|
-
|
|
25
|
-
YARD::Rake::YardocTask.new('doc') do |doc|
|
|
26
|
-
doc.options << '-m' << 'markdown' << '-M' << 'redcarpet'
|
|
27
|
-
doc.options << '--protected' << '--no-private'
|
|
28
|
-
doc.options << '-r' << 'README.md'
|
|
29
|
-
doc.options << '-o' << 'doc'
|
|
30
|
-
doc.options << '--title' << 'url_validation Documentation'.inspect
|
|
31
|
-
|
|
32
|
-
doc.files = %w(lib/**/*.rb README.md)
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
require 'rspec/core/rake_task'
|
|
36
|
-
RSpec::Core::RakeTask.new
|
|
6
|
+
RSpec::Core::RakeTask.new(:spec)
|
|
37
7
|
|
|
38
8
|
task default: :spec
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# UrlValidator's version. Lives in its own module so the gemspec can
|
|
4
|
+
# `require_relative "lib/url_validation/version"` without forcing ActiveModel
|
|
5
|
+
# to load at gem-spec-evaluation time. The UrlValidator class picks the
|
|
6
|
+
# constant up and assigns it as `UrlValidator::VERSION`.
|
|
7
|
+
module UrlValidation
|
|
8
|
+
VERSION = "2.0.0"
|
|
9
|
+
end
|
data/lib/url_validation.rb
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
require
|
|
4
|
-
require
|
|
5
|
-
require
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "addressable/uri"
|
|
4
|
+
require "httpi"
|
|
5
|
+
require "active_support/core_ext/hash/except"
|
|
6
|
+
require "active_model/validator"
|
|
7
|
+
require "active_support/core_ext/array/wrap"
|
|
8
|
+
|
|
9
|
+
require "url_validation/version"
|
|
6
10
|
|
|
7
11
|
# Validates URLs. Uses the following I18n error message keys:
|
|
8
12
|
#
|
|
@@ -30,6 +34,9 @@ require 'active_support/core_ext/array/wrap'
|
|
|
30
34
|
# request_callback: ->(request) { request.timeout = 30 }
|
|
31
35
|
# }
|
|
32
36
|
#
|
|
37
|
+
# @example Uses a GET request instead of the default HEAD request
|
|
38
|
+
# validates :link, url: {check_host: true, http_method: :get}
|
|
39
|
+
#
|
|
33
40
|
# ## Options
|
|
34
41
|
#
|
|
35
42
|
# ### Basic options
|
|
@@ -61,11 +68,16 @@ require 'active_support/core_ext/array/wrap'
|
|
|
61
68
|
# you wish to use. This allows you to drop in, e.g., a Curl client if you want.
|
|
62
69
|
# You can set the HTTPI adapter with the `:httpi_adapter` option.
|
|
63
70
|
#
|
|
71
|
+
# By default, HEAD requests are used for accessibility checks. If a server does
|
|
72
|
+
# not support HEAD requests, you can set `:http_method` to `:get` (or any other
|
|
73
|
+
# verb supported by HTTPI).
|
|
74
|
+
#
|
|
64
75
|
# | | |
|
|
65
76
|
# |:-----------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
66
77
|
# | `: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. |
|
|
67
78
|
# | `: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. |
|
|
68
79
|
# | `:httpi_adapter` | The HTTPI adapter to use for checking HTTP and HTTPS URLs (default set by the HTTPI gem). |
|
|
80
|
+
# | `:http_method` | The HTTP verb (as a Symbol) to use for the accessibility check. Defaults to `:head`. Set to `:get` for servers that do not support HEAD. |
|
|
69
81
|
#
|
|
70
82
|
# ### Other options
|
|
71
83
|
#
|
|
@@ -74,6 +86,8 @@ require 'active_support/core_ext/array/wrap'
|
|
|
74
86
|
# | `: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. |
|
|
75
87
|
|
|
76
88
|
class UrlValidator < ActiveModel::EachValidator
|
|
89
|
+
VERSION = UrlValidation::VERSION
|
|
90
|
+
|
|
77
91
|
# @private
|
|
78
92
|
CODES = {
|
|
79
93
|
continue: 100,
|
|
@@ -127,35 +141,36 @@ class UrlValidator < ActiveModel::EachValidator
|
|
|
127
141
|
variant_also_negotiates: 506,
|
|
128
142
|
insufficient_storage: 507,
|
|
129
143
|
not_extended: 510
|
|
130
|
-
}
|
|
144
|
+
}.freeze
|
|
131
145
|
|
|
132
146
|
# @private
|
|
133
147
|
def validate_each(record, attribute, value)
|
|
134
|
-
return if value.blank?
|
|
148
|
+
return if value.blank? && options.fetch(:allow_blank, true)
|
|
135
149
|
|
|
150
|
+
uri = nil
|
|
136
151
|
begin
|
|
137
152
|
uri = Addressable::URI.parse(value)
|
|
138
153
|
|
|
139
|
-
if uri.scheme.nil?
|
|
154
|
+
if uri.scheme.nil? && options[:default_scheme]
|
|
140
155
|
uri = Addressable::URI.parse("#{options[:default_scheme]}://#{value}")
|
|
141
156
|
end
|
|
142
157
|
rescue Addressable::URI::InvalidURIError
|
|
143
|
-
record.errors.add(attribute, options[:invalid_url_message] || :invalid_url)
|
|
158
|
+
record.errors.add(attribute, options[:invalid_url_message] || :invalid_url)
|
|
144
159
|
return
|
|
145
160
|
end
|
|
146
161
|
|
|
147
162
|
record.errors.add(attribute, options[:invalid_url_message] || :invalid_url) unless url_format_valid?(uri, options)
|
|
148
|
-
record.errors.add(attribute, options[:url_not_accessible_message] || :url_not_accessible) unless response = url_accessible?(uri, options)
|
|
163
|
+
record.errors.add(attribute, options[:url_not_accessible_message] || :url_not_accessible) unless (response = url_accessible?(uri, options))
|
|
149
164
|
record.errors.add(attribute, options[:url_invalid_response_message] || :url_invalid_response) unless url_response_valid?(response, options)
|
|
150
165
|
end
|
|
151
166
|
|
|
152
167
|
private
|
|
153
168
|
|
|
154
169
|
def url_format_valid?(uri, options)
|
|
155
|
-
return false unless Array.wrap(options[:scheme] || %w
|
|
170
|
+
return false unless Array.wrap(options[:scheme] || %w[http https]).include?(uri.scheme)
|
|
156
171
|
|
|
157
172
|
case uri.scheme
|
|
158
|
-
when
|
|
173
|
+
when "http", "https"
|
|
159
174
|
return http_url_format_valid?(uri)
|
|
160
175
|
else
|
|
161
176
|
return true
|
|
@@ -163,20 +178,20 @@ class UrlValidator < ActiveModel::EachValidator
|
|
|
163
178
|
end
|
|
164
179
|
|
|
165
180
|
def http_url_format_valid?(uri)
|
|
166
|
-
uri.host.present?
|
|
181
|
+
uri.host.present? && !uri.path.nil?
|
|
167
182
|
end
|
|
168
183
|
|
|
169
184
|
def url_accessible?(uri, options)
|
|
170
|
-
return true unless options[:check_host]
|
|
185
|
+
return true unless options[:check_host] || options[:check_path]
|
|
171
186
|
|
|
172
187
|
check_host = options[:check_host]
|
|
173
|
-
check_host ||= %w
|
|
174
|
-
if (schemes = Array.wrap(check_host))
|
|
175
|
-
return true
|
|
188
|
+
check_host ||= %w[http https] if options[:check_path]
|
|
189
|
+
if (schemes = Array.wrap(check_host)) && schemes.all?(String) && !schemes.include?(uri.scheme)
|
|
190
|
+
return true
|
|
176
191
|
end
|
|
177
192
|
|
|
178
193
|
case uri.scheme
|
|
179
|
-
when
|
|
194
|
+
when "http", "https"
|
|
180
195
|
return http_url_accessible?(uri, options)
|
|
181
196
|
else
|
|
182
197
|
return true
|
|
@@ -186,14 +201,16 @@ class UrlValidator < ActiveModel::EachValidator
|
|
|
186
201
|
def http_url_accessible?(uri, options)
|
|
187
202
|
request = HTTPI::Request.new(uri.to_s)
|
|
188
203
|
options[:request_callback].call(request) if options[:request_callback].respond_to?(:call)
|
|
189
|
-
|
|
190
|
-
|
|
204
|
+
method = options[:http_method] || :head
|
|
205
|
+
return HTTPI.request(method, request, options[:httpi_adapter])
|
|
206
|
+
rescue StandardError
|
|
191
207
|
return false
|
|
192
208
|
end
|
|
193
209
|
|
|
194
210
|
def url_response_valid?(response, options)
|
|
195
|
-
return true unless response.kind_of?(HTTPI::Response)
|
|
196
|
-
|
|
211
|
+
return true unless response.kind_of?(HTTPI::Response) && options[:check_path]
|
|
212
|
+
|
|
213
|
+
response_codes = (options[:check_path] == true) ? [400..499, 500..599] : Array.wrap(options[:check_path]).flatten
|
|
197
214
|
return response_codes.none? do |code| # it's good if it's not a bad response
|
|
198
215
|
case code # and it's a bad response if...
|
|
199
216
|
when Range
|
data/url_validation.gemspec
CHANGED
|
@@ -1,75 +1,49 @@
|
|
|
1
|
-
#
|
|
2
|
-
# DO NOT EDIT THIS FILE DIRECTLY
|
|
3
|
-
# Instead, edit Juwelier::Tasks in Rakefile, and run 'rake gemspec'
|
|
4
|
-
# -*- encoding: utf-8 -*-
|
|
5
|
-
# stub: url_validation 1.2.0 ruby lib
|
|
1
|
+
# frozen_string_literal: true
|
|
6
2
|
|
|
7
|
-
|
|
8
|
-
s.name = "url_validation".freeze
|
|
9
|
-
s.version = "1.2.0"
|
|
3
|
+
require_relative "lib/url_validation/version"
|
|
10
4
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
s.email = "git@timothymorgan.info".freeze
|
|
17
|
-
s.extra_rdoc_files = [
|
|
18
|
-
"LICENSE",
|
|
19
|
-
"README.md"
|
|
20
|
-
]
|
|
21
|
-
s.files = [
|
|
22
|
-
".document",
|
|
23
|
-
".rspec",
|
|
24
|
-
".ruby-gemset",
|
|
25
|
-
".ruby-version",
|
|
26
|
-
"Gemfile",
|
|
27
|
-
"Gemfile.lock",
|
|
28
|
-
"LICENSE",
|
|
29
|
-
"README.md",
|
|
30
|
-
"Rakefile",
|
|
31
|
-
"VERSION",
|
|
32
|
-
"lib/url_validation.rb",
|
|
33
|
-
"spec/spec_helper.rb",
|
|
34
|
-
"spec/url_validator_spec.rb",
|
|
35
|
-
"url_validation.gemspec"
|
|
36
|
-
]
|
|
37
|
-
s.homepage = "http://github.com/riscfuture/url_validation".freeze
|
|
38
|
-
s.required_ruby_version = Gem::Requirement.new(">= 2.0.0".freeze)
|
|
39
|
-
s.rubygems_version = "2.6.12".freeze
|
|
40
|
-
s.summary = "Simple URL validation in Rails 3+".freeze
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = "url_validation"
|
|
7
|
+
spec.version = UrlValidation::VERSION
|
|
8
|
+
spec.authors = ["Tim Morgan"]
|
|
9
|
+
spec.email = ["git@timothymorgan.info"]
|
|
41
10
|
|
|
42
|
-
|
|
43
|
-
|
|
11
|
+
spec.summary = "Simple URL validation for ActiveModel."
|
|
12
|
+
spec.description = "A simple, localizable ActiveModel::EachValidator for URL fields. " \
|
|
13
|
+
"Supports format validation as well as optional network reachability " \
|
|
14
|
+
"checks via HEAD (or any other HTTP verb) requests."
|
|
15
|
+
spec.homepage = "https://github.com/riscfuture/url_validation"
|
|
16
|
+
spec.license = "MIT"
|
|
44
17
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
end
|
|
64
|
-
else
|
|
65
|
-
s.add_dependency(%q<addressable>.freeze, [">= 0"])
|
|
66
|
-
s.add_dependency(%q<activesupport>.freeze, [">= 0"])
|
|
67
|
-
s.add_dependency(%q<activerecord>.freeze, [">= 0"])
|
|
68
|
-
s.add_dependency(%q<httpi>.freeze, [">= 0"])
|
|
69
|
-
s.add_dependency(%q<juwelier>.freeze, [">= 0"])
|
|
70
|
-
s.add_dependency(%q<yard>.freeze, [">= 0"])
|
|
71
|
-
s.add_dependency(%q<redcarpet>.freeze, [">= 0"])
|
|
72
|
-
s.add_dependency(%q<rspec>.freeze, [">= 0"])
|
|
18
|
+
spec.required_ruby_version = ">= 3.1"
|
|
19
|
+
|
|
20
|
+
spec.metadata = {
|
|
21
|
+
"homepage_uri" => spec.homepage,
|
|
22
|
+
"bug_tracker_uri" => "#{spec.homepage}/issues",
|
|
23
|
+
"changelog_uri" => "#{spec.homepage}/blob/master/CHANGELOG.md",
|
|
24
|
+
"rubygems_mfa_required" => "true"
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
spec.files = Dir.chdir(__dir__) do
|
|
28
|
+
tracked = `git ls-files -z`.split("\x0")
|
|
29
|
+
# Always include these even if not yet committed (helps local builds).
|
|
30
|
+
extra = %w[CHANGELOG.md lib/url_validation/version.rb]
|
|
31
|
+
(tracked + extra).uniq.reject do |f|
|
|
32
|
+
f.match(%r{\A(?:test|spec|features|bin|gemfiles|\.github|\.idea)/}) ||
|
|
33
|
+
f.match(%r{\A\.(?:rspec|rubocop\.yml|standard\.yml|ruby-version|ruby-gemset|gitignore|document|travis\.yml)\z}) ||
|
|
34
|
+
f.match(%r{\AGemfile(?:\.lock)?\z}) ||
|
|
35
|
+
f == "VERSION"
|
|
36
|
+
end.select { |f| File.exist?(File.join(__dir__, f)) }
|
|
73
37
|
end
|
|
74
|
-
|
|
38
|
+
spec.require_paths = ["lib"]
|
|
75
39
|
|
|
40
|
+
spec.add_dependency "activemodel", ">= 6.1"
|
|
41
|
+
spec.add_dependency "activesupport", ">= 6.1"
|
|
42
|
+
spec.add_dependency "addressable", "~> 2.8"
|
|
43
|
+
spec.add_dependency "httpi", "~> 4.0"
|
|
44
|
+
|
|
45
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
|
46
|
+
spec.add_development_dependency "rspec", "~> 3.13"
|
|
47
|
+
spec.add_development_dependency "standard", "~> 1.0"
|
|
48
|
+
spec.add_development_dependency "webmock", "~> 3.0"
|
|
49
|
+
end
|
metadata
CHANGED
|
@@ -1,153 +1,150 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: url_validation
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 2.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Tim Morgan
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
|
-
name:
|
|
13
|
+
name: activemodel
|
|
15
14
|
requirement: !ruby/object:Gem::Requirement
|
|
16
15
|
requirements:
|
|
17
16
|
- - ">="
|
|
18
17
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '
|
|
18
|
+
version: '6.1'
|
|
20
19
|
type: :runtime
|
|
21
20
|
prerelease: false
|
|
22
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
22
|
requirements:
|
|
24
23
|
- - ">="
|
|
25
24
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '
|
|
25
|
+
version: '6.1'
|
|
27
26
|
- !ruby/object:Gem::Dependency
|
|
28
27
|
name: activesupport
|
|
29
28
|
requirement: !ruby/object:Gem::Requirement
|
|
30
29
|
requirements:
|
|
31
30
|
- - ">="
|
|
32
31
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: '
|
|
32
|
+
version: '6.1'
|
|
34
33
|
type: :runtime
|
|
35
34
|
prerelease: false
|
|
36
35
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
36
|
requirements:
|
|
38
37
|
- - ">="
|
|
39
38
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: '
|
|
39
|
+
version: '6.1'
|
|
41
40
|
- !ruby/object:Gem::Dependency
|
|
42
|
-
name:
|
|
41
|
+
name: addressable
|
|
43
42
|
requirement: !ruby/object:Gem::Requirement
|
|
44
43
|
requirements:
|
|
45
|
-
- - "
|
|
44
|
+
- - "~>"
|
|
46
45
|
- !ruby/object:Gem::Version
|
|
47
|
-
version: '
|
|
46
|
+
version: '2.8'
|
|
48
47
|
type: :runtime
|
|
49
48
|
prerelease: false
|
|
50
49
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
50
|
requirements:
|
|
52
|
-
- - "
|
|
51
|
+
- - "~>"
|
|
53
52
|
- !ruby/object:Gem::Version
|
|
54
|
-
version: '
|
|
53
|
+
version: '2.8'
|
|
55
54
|
- !ruby/object:Gem::Dependency
|
|
56
55
|
name: httpi
|
|
57
56
|
requirement: !ruby/object:Gem::Requirement
|
|
58
57
|
requirements:
|
|
59
|
-
- - "
|
|
58
|
+
- - "~>"
|
|
60
59
|
- !ruby/object:Gem::Version
|
|
61
|
-
version: '0'
|
|
60
|
+
version: '4.0'
|
|
62
61
|
type: :runtime
|
|
63
62
|
prerelease: false
|
|
64
63
|
version_requirements: !ruby/object:Gem::Requirement
|
|
65
64
|
requirements:
|
|
66
|
-
- - "
|
|
65
|
+
- - "~>"
|
|
67
66
|
- !ruby/object:Gem::Version
|
|
68
|
-
version: '0'
|
|
67
|
+
version: '4.0'
|
|
69
68
|
- !ruby/object:Gem::Dependency
|
|
70
|
-
name:
|
|
69
|
+
name: rake
|
|
71
70
|
requirement: !ruby/object:Gem::Requirement
|
|
72
71
|
requirements:
|
|
73
|
-
- - "
|
|
72
|
+
- - "~>"
|
|
74
73
|
- !ruby/object:Gem::Version
|
|
75
|
-
version: '0'
|
|
74
|
+
version: '13.0'
|
|
76
75
|
type: :development
|
|
77
76
|
prerelease: false
|
|
78
77
|
version_requirements: !ruby/object:Gem::Requirement
|
|
79
78
|
requirements:
|
|
80
|
-
- - "
|
|
79
|
+
- - "~>"
|
|
81
80
|
- !ruby/object:Gem::Version
|
|
82
|
-
version: '0'
|
|
81
|
+
version: '13.0'
|
|
83
82
|
- !ruby/object:Gem::Dependency
|
|
84
|
-
name:
|
|
83
|
+
name: rspec
|
|
85
84
|
requirement: !ruby/object:Gem::Requirement
|
|
86
85
|
requirements:
|
|
87
|
-
- - "
|
|
86
|
+
- - "~>"
|
|
88
87
|
- !ruby/object:Gem::Version
|
|
89
|
-
version: '
|
|
88
|
+
version: '3.13'
|
|
90
89
|
type: :development
|
|
91
90
|
prerelease: false
|
|
92
91
|
version_requirements: !ruby/object:Gem::Requirement
|
|
93
92
|
requirements:
|
|
94
|
-
- - "
|
|
93
|
+
- - "~>"
|
|
95
94
|
- !ruby/object:Gem::Version
|
|
96
|
-
version: '
|
|
95
|
+
version: '3.13'
|
|
97
96
|
- !ruby/object:Gem::Dependency
|
|
98
|
-
name:
|
|
97
|
+
name: standard
|
|
99
98
|
requirement: !ruby/object:Gem::Requirement
|
|
100
99
|
requirements:
|
|
101
|
-
- - "
|
|
100
|
+
- - "~>"
|
|
102
101
|
- !ruby/object:Gem::Version
|
|
103
|
-
version: '0'
|
|
102
|
+
version: '1.0'
|
|
104
103
|
type: :development
|
|
105
104
|
prerelease: false
|
|
106
105
|
version_requirements: !ruby/object:Gem::Requirement
|
|
107
106
|
requirements:
|
|
108
|
-
- - "
|
|
107
|
+
- - "~>"
|
|
109
108
|
- !ruby/object:Gem::Version
|
|
110
|
-
version: '0'
|
|
109
|
+
version: '1.0'
|
|
111
110
|
- !ruby/object:Gem::Dependency
|
|
112
|
-
name:
|
|
111
|
+
name: webmock
|
|
113
112
|
requirement: !ruby/object:Gem::Requirement
|
|
114
113
|
requirements:
|
|
115
|
-
- - "
|
|
114
|
+
- - "~>"
|
|
116
115
|
- !ruby/object:Gem::Version
|
|
117
|
-
version: '0'
|
|
116
|
+
version: '3.0'
|
|
118
117
|
type: :development
|
|
119
118
|
prerelease: false
|
|
120
119
|
version_requirements: !ruby/object:Gem::Requirement
|
|
121
120
|
requirements:
|
|
122
|
-
- - "
|
|
121
|
+
- - "~>"
|
|
123
122
|
- !ruby/object:Gem::Version
|
|
124
|
-
version: '0'
|
|
125
|
-
description: A simple, localizable EachValidator for URL fields
|
|
126
|
-
|
|
123
|
+
version: '3.0'
|
|
124
|
+
description: A simple, localizable ActiveModel::EachValidator for URL fields. Supports
|
|
125
|
+
format validation as well as optional network reachability checks via HEAD (or any
|
|
126
|
+
other HTTP verb) requests.
|
|
127
|
+
email:
|
|
128
|
+
- git@timothymorgan.info
|
|
127
129
|
executables: []
|
|
128
130
|
extensions: []
|
|
129
|
-
extra_rdoc_files:
|
|
130
|
-
- LICENSE
|
|
131
|
-
- README.md
|
|
131
|
+
extra_rdoc_files: []
|
|
132
132
|
files:
|
|
133
|
-
-
|
|
134
|
-
- ".rspec"
|
|
135
|
-
- ".ruby-gemset"
|
|
136
|
-
- ".ruby-version"
|
|
137
|
-
- Gemfile
|
|
138
|
-
- Gemfile.lock
|
|
133
|
+
- CHANGELOG.md
|
|
139
134
|
- LICENSE
|
|
140
135
|
- README.md
|
|
141
136
|
- Rakefile
|
|
142
|
-
- VERSION
|
|
143
137
|
- lib/url_validation.rb
|
|
144
|
-
-
|
|
145
|
-
- spec/url_validator_spec.rb
|
|
138
|
+
- lib/url_validation/version.rb
|
|
146
139
|
- url_validation.gemspec
|
|
147
|
-
homepage:
|
|
148
|
-
licenses:
|
|
149
|
-
|
|
150
|
-
|
|
140
|
+
homepage: https://github.com/riscfuture/url_validation
|
|
141
|
+
licenses:
|
|
142
|
+
- MIT
|
|
143
|
+
metadata:
|
|
144
|
+
homepage_uri: https://github.com/riscfuture/url_validation
|
|
145
|
+
bug_tracker_uri: https://github.com/riscfuture/url_validation/issues
|
|
146
|
+
changelog_uri: https://github.com/riscfuture/url_validation/blob/master/CHANGELOG.md
|
|
147
|
+
rubygems_mfa_required: 'true'
|
|
151
148
|
rdoc_options: []
|
|
152
149
|
require_paths:
|
|
153
150
|
- lib
|
|
@@ -155,16 +152,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
155
152
|
requirements:
|
|
156
153
|
- - ">="
|
|
157
154
|
- !ruby/object:Gem::Version
|
|
158
|
-
version:
|
|
155
|
+
version: '3.1'
|
|
159
156
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
160
157
|
requirements:
|
|
161
158
|
- - ">="
|
|
162
159
|
- !ruby/object:Gem::Version
|
|
163
160
|
version: '0'
|
|
164
161
|
requirements: []
|
|
165
|
-
|
|
166
|
-
rubygems_version: 2.6.12
|
|
167
|
-
signing_key:
|
|
162
|
+
rubygems_version: 4.0.11
|
|
168
163
|
specification_version: 4
|
|
169
|
-
summary: Simple URL validation
|
|
164
|
+
summary: Simple URL validation for ActiveModel.
|
|
170
165
|
test_files: []
|
data/.document
DELETED
data/.rspec
DELETED
data/.ruby-gemset
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
url_validation
|
data/.ruby-version
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
2.4.1
|
data/Gemfile
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
source 'https://rubygems.org'
|
|
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
|
-
# PUBLISHING
|
|
10
|
-
gem 'juwelier'
|
|
11
|
-
|
|
12
|
-
# DOCS
|
|
13
|
-
gem 'yard', require: nil
|
|
14
|
-
gem 'redcarpet', require: nil
|
|
15
|
-
|
|
16
|
-
# SPECS
|
|
17
|
-
gem 'rspec'
|
|
18
|
-
end
|
data/Gemfile.lock
DELETED
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
GEM
|
|
2
|
-
remote: https://rubygems.org/
|
|
3
|
-
specs:
|
|
4
|
-
activemodel (5.1.1)
|
|
5
|
-
activesupport (= 5.1.1)
|
|
6
|
-
activerecord (5.1.1)
|
|
7
|
-
activemodel (= 5.1.1)
|
|
8
|
-
activesupport (= 5.1.1)
|
|
9
|
-
arel (~> 8.0)
|
|
10
|
-
activesupport (5.1.1)
|
|
11
|
-
concurrent-ruby (~> 1.0, >= 1.0.2)
|
|
12
|
-
i18n (~> 0.7)
|
|
13
|
-
minitest (~> 5.1)
|
|
14
|
-
tzinfo (~> 1.1)
|
|
15
|
-
addressable (2.4.0)
|
|
16
|
-
arel (8.0.0)
|
|
17
|
-
builder (3.2.3)
|
|
18
|
-
concurrent-ruby (1.0.5)
|
|
19
|
-
descendants_tracker (0.0.4)
|
|
20
|
-
thread_safe (~> 0.3, >= 0.3.1)
|
|
21
|
-
diff-lcs (1.3)
|
|
22
|
-
faraday (0.9.2)
|
|
23
|
-
multipart-post (>= 1.2, < 3)
|
|
24
|
-
git (1.3.0)
|
|
25
|
-
github_api (0.17.0)
|
|
26
|
-
addressable (~> 2.4.0)
|
|
27
|
-
descendants_tracker (~> 0.0.4)
|
|
28
|
-
faraday (~> 0.8, < 0.10)
|
|
29
|
-
hashie (>= 3.4)
|
|
30
|
-
mime-types (>= 1.16, < 3.0)
|
|
31
|
-
oauth2 (~> 1.0)
|
|
32
|
-
hashie (3.5.5)
|
|
33
|
-
highline (1.7.8)
|
|
34
|
-
httpi (2.4.2)
|
|
35
|
-
rack
|
|
36
|
-
socksify
|
|
37
|
-
i18n (0.8.4)
|
|
38
|
-
juwelier (2.4.5)
|
|
39
|
-
builder
|
|
40
|
-
bundler (>= 1.13)
|
|
41
|
-
git (>= 1.2.5)
|
|
42
|
-
github_api
|
|
43
|
-
highline (>= 1.6.15)
|
|
44
|
-
kamelcase (~> 0)
|
|
45
|
-
nokogiri (>= 1.5.10)
|
|
46
|
-
psych (~> 2.2)
|
|
47
|
-
rake
|
|
48
|
-
rdoc
|
|
49
|
-
semver2
|
|
50
|
-
jwt (1.5.6)
|
|
51
|
-
kamelcase (0.0.0)
|
|
52
|
-
semver2 (~> 3)
|
|
53
|
-
mime-types (2.99.3)
|
|
54
|
-
mini_portile2 (2.1.0)
|
|
55
|
-
minitest (5.10.2)
|
|
56
|
-
multi_json (1.12.1)
|
|
57
|
-
multi_xml (0.6.0)
|
|
58
|
-
multipart-post (2.0.0)
|
|
59
|
-
nokogiri (1.7.2)
|
|
60
|
-
mini_portile2 (~> 2.1.0)
|
|
61
|
-
oauth2 (1.3.1)
|
|
62
|
-
faraday (>= 0.8, < 0.12)
|
|
63
|
-
jwt (~> 1.0)
|
|
64
|
-
multi_json (~> 1.3)
|
|
65
|
-
multi_xml (~> 0.5)
|
|
66
|
-
rack (>= 1.2, < 3)
|
|
67
|
-
psych (2.2.4)
|
|
68
|
-
rack (2.0.3)
|
|
69
|
-
rake (12.0.0)
|
|
70
|
-
rdoc (5.1.0)
|
|
71
|
-
redcarpet (3.4.0)
|
|
72
|
-
rspec (3.6.0)
|
|
73
|
-
rspec-core (~> 3.6.0)
|
|
74
|
-
rspec-expectations (~> 3.6.0)
|
|
75
|
-
rspec-mocks (~> 3.6.0)
|
|
76
|
-
rspec-core (3.6.0)
|
|
77
|
-
rspec-support (~> 3.6.0)
|
|
78
|
-
rspec-expectations (3.6.0)
|
|
79
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
|
80
|
-
rspec-support (~> 3.6.0)
|
|
81
|
-
rspec-mocks (3.6.0)
|
|
82
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
|
83
|
-
rspec-support (~> 3.6.0)
|
|
84
|
-
rspec-support (3.6.0)
|
|
85
|
-
semver2 (3.4.2)
|
|
86
|
-
socksify (1.7.1)
|
|
87
|
-
thread_safe (0.3.6)
|
|
88
|
-
tzinfo (1.2.3)
|
|
89
|
-
thread_safe (~> 0.1)
|
|
90
|
-
yard (0.9.9)
|
|
91
|
-
|
|
92
|
-
PLATFORMS
|
|
93
|
-
ruby
|
|
94
|
-
|
|
95
|
-
DEPENDENCIES
|
|
96
|
-
activerecord
|
|
97
|
-
activesupport
|
|
98
|
-
addressable
|
|
99
|
-
httpi
|
|
100
|
-
juwelier
|
|
101
|
-
redcarpet
|
|
102
|
-
rspec
|
|
103
|
-
yard
|
|
104
|
-
|
|
105
|
-
BUNDLED WITH
|
|
106
|
-
1.15.0
|
data/VERSION
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
1.2.0
|
data/spec/spec_helper.rb
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
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
|
data/spec/url_validator_spec.rb
DELETED
|
@@ -1,235 +0,0 @@
|
|
|
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: %i(field), allow_nil: true)
|
|
17
|
-
@validator.validate_each(@record, :field, nil)
|
|
18
|
-
expect(@record.errors).to be_empty
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
it "should allow \"\" if :allow_blank is set" do
|
|
22
|
-
@validator = UrlValidator.new(attributes: %i(field), allow_blank: true)
|
|
23
|
-
@validator.validate_each(@record, :field, "")
|
|
24
|
-
expect(@record.errors).to 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: %i(field), scheme: 'http')
|
|
31
|
-
@validator.validate_each(@record, :field, 'http://www.apple.com')
|
|
32
|
-
expect(@record.errors).to be_empty
|
|
33
|
-
|
|
34
|
-
@validator.validate_each(@record, :field, 'https://www.apple.com')
|
|
35
|
-
expect(@record.errors[:field].first).to 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: %i(field), scheme: %w(http https))
|
|
40
|
-
@validator.validate_each(@record, :field, 'http://www.apple.com')
|
|
41
|
-
expect(@record.errors).to be_empty
|
|
42
|
-
@validator.validate_each(@record, :field, 'https://www.apple.com')
|
|
43
|
-
expect(@record.errors).to be_empty
|
|
44
|
-
|
|
45
|
-
@validator.validate_each(@record, :field, 'ftp://www.apple.com')
|
|
46
|
-
expect(@record.errors[:field].first).to include('invalid_url')
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
it "should try a default scheme if :default_scheme is set" do
|
|
50
|
-
@validator = UrlValidator.new(attributes: %i(field), scheme: 'http', default_scheme: 'http')
|
|
51
|
-
@validator.validate_each(@record, :field, 'www.apple.com')
|
|
52
|
-
expect(@record.errors).to 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: %i(field))
|
|
58
|
-
|
|
59
|
-
%w(
|
|
60
|
-
http:sdg.sdfg/
|
|
61
|
-
http/sdg.d
|
|
62
|
-
http:://dsfg.dsfg/
|
|
63
|
-
http//sdg..g
|
|
64
|
-
http://://sdfg.f).each do |uri|
|
|
65
|
-
@record.errors.clear
|
|
66
|
-
@validator.validate_each(@record, :field, uri)
|
|
67
|
-
expect(@record.errors[:field].first).to include('invalid_url')
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
it "should not allow invalid scheme formats" do
|
|
72
|
-
@validator = UrlValidator.new(attributes: %i(field))
|
|
73
|
-
@validator.validate_each(@record, :field, ' https://www.apple.com')
|
|
74
|
-
expect(@record.errors[:field].first).to include('invalid_url')
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
context '[accessibility]' do
|
|
80
|
-
context '[:check_host]' do
|
|
81
|
-
it "should only validate if the host is accessible when :check_host is set" do
|
|
82
|
-
@validator = UrlValidator.new(attributes: %i(field))
|
|
83
|
-
@validator.validate_each(@record, :field, 'http://www.invalid.tld')
|
|
84
|
-
expect(@record.errors).to be_empty
|
|
85
|
-
|
|
86
|
-
@validator = UrlValidator.new(attributes: %i(field), check_host: true)
|
|
87
|
-
@validator.validate_each(@record, :field, 'http://www.invalid.tld')
|
|
88
|
-
expect(@record.errors[:field].first).to include('url_not_accessible')
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
it "should not perform the accessibility check if :check_host is set to 'http' and the URL scheme is not HTTP" do
|
|
92
|
-
@validator = UrlValidator.new(attributes: %i(field), check_host: 'http')
|
|
93
|
-
@validator.validate_each(@record, :field, 'https://www.invalid.tld')
|
|
94
|
-
expect(@record.errors).to be_empty
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
it "should only validate if the host is accessible when :check_host is set to 'http' and the URL scheme is HTTP" do
|
|
98
|
-
@validator = UrlValidator.new(attributes: %i(field), check_host: 'http')
|
|
99
|
-
@validator.validate_each(@record, :field, 'http://www.invalid.tld')
|
|
100
|
-
expect(@record.errors[:field].first).to include('url_not_accessible')
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
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
|
|
104
|
-
@validator = UrlValidator.new(attributes: %i(field), check_host: %w(http https), scheme: %w(ftp http https))
|
|
105
|
-
@validator.validate_each(@record, :field, 'ftp://www.invalid.tld')
|
|
106
|
-
expect(@record.errors).to be_empty
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
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
|
|
110
|
-
@validator = UrlValidator.new(attributes: %i(field), check_host: %w(http https))
|
|
111
|
-
@validator.validate_each(@record, :field, 'http://www.invalid.tld')
|
|
112
|
-
expect(@record.errors[:field].first).to include('url_not_accessible')
|
|
113
|
-
|
|
114
|
-
@validator = UrlValidator.new(attributes: %i(field), check_host: %w(http https))
|
|
115
|
-
@validator.validate_each(@record, :field, 'https://www.invalid.tld')
|
|
116
|
-
expect(@record.errors[:field].first).to include('url_not_accessible')
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
it "should only validate the host" do
|
|
120
|
-
@validator = UrlValidator.new(attributes: %i(field), check_host: true)
|
|
121
|
-
@validator.validate_each(@record, :field, 'http://www.google.com/sdgsdgf')
|
|
122
|
-
expect(@record.errors).to be_empty
|
|
123
|
-
end
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
context '[:check_path]' do
|
|
127
|
-
it "should not validate if the response code is equal to the Integer value of this option" do
|
|
128
|
-
@validator = UrlValidator.new(attributes: %i(field), check_path: 404)
|
|
129
|
-
@validator.validate_each(@record, :field, 'http://www.google.com/sdgsdgf')
|
|
130
|
-
expect(@record.errors[:field].first).to include('url_invalid_response')
|
|
131
|
-
|
|
132
|
-
@record.errors.clear
|
|
133
|
-
|
|
134
|
-
@validator = UrlValidator.new(attributes: %i(field), check_path: 405)
|
|
135
|
-
@validator.validate_each(@record, :field, 'http://www.google.com/sdgsdgf')
|
|
136
|
-
expect(@record.errors[:field]).to be_empty
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
it "should not validate if the response code is equal to the Symbol value of this option" do
|
|
140
|
-
@validator = UrlValidator.new(attributes: %i(field), check_path: :not_found)
|
|
141
|
-
@validator.validate_each(@record, :field, 'http://www.google.com/sdgsdgf')
|
|
142
|
-
expect(@record.errors[:field].first).to include('url_invalid_response')
|
|
143
|
-
|
|
144
|
-
@record.errors.clear
|
|
145
|
-
|
|
146
|
-
@validator = UrlValidator.new(attributes: %i(field), check_path: :unauthorized)
|
|
147
|
-
@validator.validate_each(@record, :field, 'http://www.google.com/sdgsdgf')
|
|
148
|
-
expect(@record.errors[:field]).to be_empty
|
|
149
|
-
end
|
|
150
|
-
|
|
151
|
-
it "should not validate if the response code is within the Range value of this option" do
|
|
152
|
-
@validator = UrlValidator.new(attributes: %i(field), check_path: 400..499)
|
|
153
|
-
@validator.validate_each(@record, :field, 'http://www.google.com/sdgsdgf')
|
|
154
|
-
expect(@record.errors[:field].first).to include('url_invalid_response')
|
|
155
|
-
|
|
156
|
-
@record.errors.clear
|
|
157
|
-
|
|
158
|
-
@validator = UrlValidator.new(attributes: %i(field), check_path: 500..599)
|
|
159
|
-
@validator.validate_each(@record, :field, 'http://www.google.com/sdgsdgf')
|
|
160
|
-
expect(@record.errors[:field]).to be_empty
|
|
161
|
-
end
|
|
162
|
-
|
|
163
|
-
it "should not validate if the response code is equal to the Integer value contained in the Array value of this option" do
|
|
164
|
-
@validator = UrlValidator.new(attributes: %i(field), check_path: [404, 405])
|
|
165
|
-
@validator.validate_each(@record, :field, 'http://www.google.com/sdgsdgf')
|
|
166
|
-
expect(@record.errors[:field].first).to include('url_invalid_response')
|
|
167
|
-
|
|
168
|
-
@record.errors.clear
|
|
169
|
-
|
|
170
|
-
@validator = UrlValidator.new(attributes: %i(field), check_path: [405, 406])
|
|
171
|
-
@validator.validate_each(@record, :field, 'http://www.google.com/sdgsdgf')
|
|
172
|
-
expect(@record.errors[:field]).to be_empty
|
|
173
|
-
end
|
|
174
|
-
|
|
175
|
-
it "should not validate if the response code is equal to the Symbol value contained in the Array value of this option" do
|
|
176
|
-
@validator = UrlValidator.new(attributes: %i(field), check_path: %i(not_found unauthorized))
|
|
177
|
-
@validator.validate_each(@record, :field, 'http://www.google.com/sdgsdgf')
|
|
178
|
-
expect(@record.errors[:field].first).to include('url_invalid_response')
|
|
179
|
-
|
|
180
|
-
@record.errors.clear
|
|
181
|
-
|
|
182
|
-
@validator = UrlValidator.new(attributes: %i(field), check_path: %i(unauthorized moved_permanently))
|
|
183
|
-
@validator.validate_each(@record, :field, 'http://www.google.com/sdgsdgf')
|
|
184
|
-
expect(@record.errors[:field]).to be_empty
|
|
185
|
-
end
|
|
186
|
-
|
|
187
|
-
it "should not validate if the response code is equal to the Range value contained in the Array value of this option" do
|
|
188
|
-
@validator = UrlValidator.new(attributes: %i(field), check_path: [400..499, 500..599])
|
|
189
|
-
@validator.validate_each(@record, :field, 'http://www.google.com/sdgsdgf')
|
|
190
|
-
expect(@record.errors[:field].first).to include('url_invalid_response')
|
|
191
|
-
|
|
192
|
-
@record.errors.clear
|
|
193
|
-
|
|
194
|
-
@validator = UrlValidator.new(attributes: %i(field), check_path: [500..599, 300..399])
|
|
195
|
-
@validator.validate_each(@record, :field, 'http://www.google.com/sdgsdgf')
|
|
196
|
-
expect(@record.errors[:field]).to be_empty
|
|
197
|
-
end
|
|
198
|
-
|
|
199
|
-
it "should skip validation by default" do
|
|
200
|
-
@validator = UrlValidator.new(attributes: %i(field), check_path: nil)
|
|
201
|
-
@validator.validate_each(@record, :field, 'http://www.google.com/sdgsdgf')
|
|
202
|
-
expect(@record.errors[:field]).to be_empty
|
|
203
|
-
end
|
|
204
|
-
|
|
205
|
-
it "should not validate 4xx and 5xx response codes if the value is true" do
|
|
206
|
-
@validator = UrlValidator.new(attributes: %i(field), check_path: true)
|
|
207
|
-
@validator.validate_each(@record, :field, 'http://www.google.com/sdgsdgf')
|
|
208
|
-
expect(@record.errors[:field].first).to include('url_invalid_response')
|
|
209
|
-
end
|
|
210
|
-
|
|
211
|
-
it "should skip validation for non-HTTP URLs" do
|
|
212
|
-
@validator = UrlValidator.new(attributes: %i(field), check_path: true, scheme: %w(ftp http https))
|
|
213
|
-
@validator.validate_each(@record, :field, 'ftp://ftp.sdgasdgohaodgh.com/sdgjsdg')
|
|
214
|
-
expect(@record.errors[:field]).to be_empty
|
|
215
|
-
end
|
|
216
|
-
end
|
|
217
|
-
|
|
218
|
-
context '[:httpi_adapter]' do
|
|
219
|
-
it "should use the specified HTTPI adapter" do
|
|
220
|
-
@validator = UrlValidator.new(attributes: %i(field), httpi_adapter: :curl, check_host: true)
|
|
221
|
-
expect(HTTPI).to receive(:get).once.with(an_instance_of(HTTPI::Request), :curl).and_return(false)
|
|
222
|
-
@validator.validate_each(@record, :field, 'http://www.google.com/sdgsdgf')
|
|
223
|
-
end
|
|
224
|
-
end
|
|
225
|
-
|
|
226
|
-
context '[:request_callback]' do
|
|
227
|
-
it "should be yielded the HTTPI request" do
|
|
228
|
-
called = false
|
|
229
|
-
@validator = UrlValidator.new(attributes: %i(field), check_host: true, request_callback: ->(request) { called = true; expect(request).to be_kind_of(HTTPI::Request) })
|
|
230
|
-
@validator.validate_each(@record, :field, 'http://www.google.com/sdgsdgf')
|
|
231
|
-
expect(called).to eql(true)
|
|
232
|
-
end
|
|
233
|
-
end
|
|
234
|
-
end
|
|
235
|
-
end
|