ficon 0.4 → 0.6
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 +4 -4
- data/lib/ficon/version.rb +1 -1
- data/lib/ficon.rb +65 -42
- data/test/ficon_test.rb +151 -45
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 95a5b1a8dba294c92d13f898bde371078e1927d67cb9e4af351608647f916d2f
|
4
|
+
data.tar.gz: 06f32b6dc310b8c7ea7dba49672f2ae85a8f1eaac890938414d27b031bf0808c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bf4e5662d4b7322e559dd116524453025cd23d76407395c6da71ed7d15e8c8298f87ac97009c5ab52b551bfed6f1cc3bc61ba5f730e026340b09c9faef355161
|
7
|
+
data.tar.gz: df182b513fe144fca1d6a5eb6d5a2e58c4d92b69df063ce6df08a0567d7e7a83d9cef0c34a464778723f664e3650f95aee49b13814f1913133912ab81f83cc12
|
data/lib/ficon/version.rb
CHANGED
data/lib/ficon.rb
CHANGED
@@ -64,9 +64,15 @@ class Ficon
|
|
64
64
|
end
|
65
65
|
|
66
66
|
def process
|
67
|
-
|
68
|
-
|
69
|
-
|
67
|
+
document = doc
|
68
|
+
if document
|
69
|
+
@site[:images] = self.class.site_images(@uri, document) || []
|
70
|
+
@site[:page_images] = self.class.page_images(@uri, document) || []
|
71
|
+
other_page_data(document)
|
72
|
+
else
|
73
|
+
@site[:images] = []
|
74
|
+
@site[:page_images] = []
|
75
|
+
end
|
70
76
|
nil
|
71
77
|
end
|
72
78
|
|
@@ -82,13 +88,9 @@ class Ficon
|
|
82
88
|
report_lines.join("\n") + "\n"
|
83
89
|
end
|
84
90
|
|
85
|
-
def site_icons = @site[:images]
|
86
|
-
|
87
|
-
def site_icon = site_icons&.first
|
88
|
-
|
89
|
-
def page_images = @site[:page_images]
|
91
|
+
def site_icons = @site[:images] || []
|
90
92
|
|
91
|
-
def
|
93
|
+
def page_images = @site[:page_images] || []
|
92
94
|
|
93
95
|
def title = @site[:title]
|
94
96
|
|
@@ -98,11 +100,11 @@ class Ficon
|
|
98
100
|
Cache.clear_cache
|
99
101
|
end
|
100
102
|
|
101
|
-
def other_page_data
|
102
|
-
@site[:title] =
|
103
|
-
@site[:description] =
|
104
|
-
canonical =
|
105
|
-
@site[:canonical] = canonical unless canonical == @
|
103
|
+
def other_page_data(document)
|
104
|
+
@site[:title] = document.at_xpath("//meta[@property='og:title']/@content")&.value || document.at_xpath("//title")&.text&.strip
|
105
|
+
@site[:description] = document.at_xpath("//meta[@property='og:description']/@content")&.value
|
106
|
+
canonical = document.at_xpath("//link[@rel='canonical']/@href")&.value
|
107
|
+
@site[:canonical] = canonical unless canonical == @uri.to_s
|
106
108
|
end
|
107
109
|
|
108
110
|
def self.site_images(uri, doc)
|
@@ -137,6 +139,34 @@ class Ficon
|
|
137
139
|
parsed_candidate.to_s
|
138
140
|
end
|
139
141
|
|
142
|
+
def classify_response_status(response)
|
143
|
+
case response.code.to_i
|
144
|
+
when 200..299
|
145
|
+
ALIVE
|
146
|
+
when 404, 410
|
147
|
+
DEAD
|
148
|
+
when 401, 403, 429
|
149
|
+
BLOCKED
|
150
|
+
when 500..599
|
151
|
+
SICK
|
152
|
+
else
|
153
|
+
SICK
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def classify_exception_status(exception)
|
158
|
+
case exception
|
159
|
+
when SocketError, Resolv::ResolvError
|
160
|
+
DEAD # DNS resolution failures
|
161
|
+
when Net::HTTPError, Timeout::Error, Errno::ECONNREFUSED
|
162
|
+
SICK # Network issues worth retrying
|
163
|
+
when OpenSSL::SSL::SSLError
|
164
|
+
SICK # SSL certificate errors
|
165
|
+
else
|
166
|
+
SICK # Default to retryable for unknown errors
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
140
170
|
private
|
141
171
|
|
142
172
|
def fetch_url(uri, redirect_limit = 5)
|
@@ -173,35 +203,28 @@ class Ficon
|
|
173
203
|
end
|
174
204
|
rescue => e
|
175
205
|
@url_status = classify_exception_status(e)
|
206
|
+
|
207
|
+
# If HTTP request failed and we're using HTTP, try HTTPS automatically
|
208
|
+
if uri.scheme == "http" &&
|
209
|
+
!uri.to_s.include?("://localhost") &&
|
210
|
+
!uri.host.match?(/^\d+\.\d+\.\d+\.\d+$/)
|
211
|
+
puts "HTTP request failed, trying HTTPS for #{uri}"
|
212
|
+
https_uri = uri.dup
|
213
|
+
https_uri.scheme = "https"
|
214
|
+
https_uri.port = 443 if https_uri.port == 80
|
215
|
+
|
216
|
+
begin
|
217
|
+
https_response = fetch_url(https_uri, redirect_limit)
|
218
|
+
if https_response
|
219
|
+
puts "HTTPS request succeeded, using HTTPS URL"
|
220
|
+
return https_response
|
221
|
+
end
|
222
|
+
rescue => https_error
|
223
|
+
puts "HTTPS fallback also failed: #{https_error.inspect}"
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
176
227
|
puts "Failed to fetch #{uri}: #{e.inspect}"
|
177
228
|
nil
|
178
229
|
end
|
179
|
-
|
180
|
-
def classify_response_status(response)
|
181
|
-
case response.code.to_i
|
182
|
-
when 200..299
|
183
|
-
ALIVE
|
184
|
-
when 404, 410
|
185
|
-
DEAD
|
186
|
-
when 401, 403, 429
|
187
|
-
BLOCKED
|
188
|
-
when 500..599
|
189
|
-
SICK
|
190
|
-
else
|
191
|
-
SICK
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
|
-
def classify_exception_status(exception)
|
196
|
-
case exception
|
197
|
-
when SocketError, Resolv::ResolutionError
|
198
|
-
DEAD # DNS resolution failures
|
199
|
-
when Net::HTTPError, Timeout::Error, Errno::ECONNREFUSED
|
200
|
-
SICK # Network issues worth retrying
|
201
|
-
when OpenSSL::SSL::SSLError
|
202
|
-
SICK # SSL certificate errors
|
203
|
-
else
|
204
|
-
SICK # Default to retryable for unknown errors
|
205
|
-
end
|
206
|
-
end
|
207
230
|
end
|
data/test/ficon_test.rb
CHANGED
@@ -1,72 +1,178 @@
|
|
1
|
-
#require 'rubygems'
|
2
|
-
require
|
1
|
+
# require 'rubygems'
|
2
|
+
require "debug"
|
3
|
+
require "resolv"
|
3
4
|
|
4
5
|
require "minitest/autorun"
|
5
6
|
|
6
7
|
PathHere = File.dirname(__FILE__)
|
7
8
|
$LOAD_PATH.unshift File.join(PathHere, "..", "lib")
|
8
9
|
|
9
|
-
require
|
10
|
-
|
11
|
-
SiteTests = []
|
12
|
-
SiteTests << { html: %Q{<meta name="msapplication-TileImage" content="https://s.yimg.com/pw/images/favicon-msapplication-tileimage.png"/> }, value: 'https://s.yimg.com/pw/images/favicon-msapplication-tileimage.png' }
|
13
|
-
SiteTests << { html: %Q{<link rel="shortcut icon" type="image/ico" href="https://s.yimg.com/pw/favicon.ico"> }, value: 'https://s.yimg.com/pw/favicon.ico' }
|
14
|
-
SiteTests << { html: %Q{<link href="/apple-touch-icon.png" rel="apple-touch-icon-precomposed">}, value: 'https://site.com/apple-touch-icon.png' }
|
15
|
-
SiteTests << { html: %Q{<link rel="shortcut icon" href="/wp-content/themes/torrentfreakredux/assets/img/icons/favicon.png">}, value: 'https://site.com/wp-content/themes/torrentfreakredux/assets/img/icons/favicon.png' }
|
16
|
-
SiteTests << { html: %Q{<link rel="apple-touch-icon-precomposed" href="/wp-content/themes/torrentfreakredux/assets/img/icons/57.png">}, value: 'https://site.com/wp-content/themes/torrentfreakredux/assets/img/icons/57.png' }
|
17
|
-
SiteTests << { html: %Q{<link rel="apple-touch-icon-precomposed" sizes="114x114" href="/wp-content/themes/torrentfreakredux/assets/img/icons/114.png">}, value: 'https://site.com/wp-content/themes/torrentfreakredux/assets/img/icons/114.png' }
|
18
|
-
SiteTests << { html: %Q{<link rel="apple-touch-icon-precomposed" sizes="72x72" href="/wp-content/themes/torrentfreakredux/assets/img/icons/72.png">}, value: 'https://site.com/wp-content/themes/torrentfreakredux/assets/img/icons/72.png' }
|
19
|
-
SiteTests << { html: %Q{<link rel="apple-touch-icon-precomposed" sizes="144x144" href="/wp-content/themes/torrentfreakredux/assets/img/icons/144.png">}, value: 'https://site.com/wp-content/themes/torrentfreakredux/assets/img/icons/144.png' }
|
20
|
-
SiteTests << { html: %Q{<link rel="shortcut icon" href="/favicon.png">}, value: 'https://site.com/favicon.png' }
|
21
|
-
SiteTests << { html: %Q{<link rel="shortcut icon" href="favicon.ico" />}, value: 'https://site.com/favicon.ico' }
|
22
|
-
SiteTests << { html: %Q{<link rel="apple-touch-icon" href="/apple-touch-icon.png">}, value: 'https://site.com/apple-touch-icon.png' }
|
23
|
-
SiteTests << { html: %Q{<link rel="shortcut icon" href="http://example.com/myicon.ico" />}, value: 'http://example.com/myicon.ico'}
|
24
|
-
SiteTests << { html: %Q{<link rel="icon" href="http://example.com/image.ico" />}, value: 'http://example.com/image.ico' }
|
25
|
-
SiteTests << { html: %Q{<link rel="icon" type="image/vnd.microsoft.icon" href="http://example.com/image.ico" />}, value: 'http://example.com/image.ico' }
|
26
|
-
SiteTests << { html: %Q{<link rel="icon" type="image/png" href="http://example.com/image.png" />}, value: 'http://example.com/image.png' }
|
27
|
-
SiteTests << { html: %Q{<link rel="icon" type="image/gif" href="http://example.com/image.gif" />}, value: 'http://example.com/image.gif' }
|
28
|
-
SiteTests << { html: %Q{<link rel="icon" type="image/x-icon" href="http://example.com/image.ico"/>}, value: 'http://example.com/image.ico' }
|
29
|
-
SiteTests << { html: %Q{<link rel="shortcut icon" href="https://fbstatic-a.akamaihd.net/rsrc.php/yl/r/H3nktOa7ZMg.ico" />}, value: 'https://fbstatic-a.akamaihd.net/rsrc.php/yl/r/H3nktOa7ZMg.ico' }
|
30
|
-
SiteTests << { html: %Q{<link rel="icon" type="image/vnd.microsoft.icon" href="/viconline/img/favicon.ico?1393375504" />}, value: 'https://site.com/viconline/img/favicon.ico?1393375504' }
|
31
|
-
SiteTests << { html: %Q{<link rel="shortcut icon" type="image/x-icon" href="/viconline/img/favicon.ico?1393375504" />}, value: 'https://site.com/viconline/img/favicon.ico?1393375504' }
|
32
|
-
SiteTests << { html: %Q{<meta name="msapplication-TileImage" content="/win8-tile-144.png"/><meta name="msapplication-TileColor" content="#00aced"/>}, value: 'https://site.com/win8-tile-144.png' }
|
33
|
-
|
34
|
-
PageTests = []
|
35
|
-
PageTests << { html: %Q{<meta property="og:image" content="https://www.facebook.com/images/fb_icon_325x325.png" />}, value: 'https://www.facebook.com/images/fb_icon_325x325.png' }
|
10
|
+
require "ficon"
|
36
11
|
|
12
|
+
SiteTests = []
|
13
|
+
SiteTests << {html: %(<meta name="msapplication-TileImage" content="https://s.yimg.com/pw/images/favicon-msapplication-tileimage.png"/> ), value: "https://s.yimg.com/pw/images/favicon-msapplication-tileimage.png"}
|
14
|
+
SiteTests << {html: %(<link rel="shortcut icon" type="image/ico" href="https://s.yimg.com/pw/favicon.ico"> ), value: "https://s.yimg.com/pw/favicon.ico"}
|
15
|
+
SiteTests << {html: %(<link href="/apple-touch-icon.png" rel="apple-touch-icon-precomposed">), value: "https://site.com/apple-touch-icon.png"}
|
16
|
+
SiteTests << {html: %(<link rel="shortcut icon" href="/wp-content/themes/torrentfreakredux/assets/img/icons/favicon.png">), value: "https://site.com/wp-content/themes/torrentfreakredux/assets/img/icons/favicon.png"}
|
17
|
+
SiteTests << {html: %(<link rel="apple-touch-icon-precomposed" href="/wp-content/themes/torrentfreakredux/assets/img/icons/57.png">), value: "https://site.com/wp-content/themes/torrentfreakredux/assets/img/icons/57.png"}
|
18
|
+
SiteTests << {html: %(<link rel="apple-touch-icon-precomposed" sizes="114x114" href="/wp-content/themes/torrentfreakredux/assets/img/icons/114.png">), value: "https://site.com/wp-content/themes/torrentfreakredux/assets/img/icons/114.png"}
|
19
|
+
SiteTests << {html: %(<link rel="apple-touch-icon-precomposed" sizes="72x72" href="/wp-content/themes/torrentfreakredux/assets/img/icons/72.png">), value: "https://site.com/wp-content/themes/torrentfreakredux/assets/img/icons/72.png"}
|
20
|
+
SiteTests << {html: %(<link rel="apple-touch-icon-precomposed" sizes="144x144" href="/wp-content/themes/torrentfreakredux/assets/img/icons/144.png">), value: "https://site.com/wp-content/themes/torrentfreakredux/assets/img/icons/144.png"}
|
21
|
+
SiteTests << {html: %(<link rel="shortcut icon" href="/favicon.png">), value: "https://site.com/favicon.png"}
|
22
|
+
SiteTests << {html: %(<link rel="shortcut icon" href="favicon.ico" />), value: "https://site.com/favicon.ico"}
|
23
|
+
SiteTests << {html: %(<link rel="apple-touch-icon" href="/apple-touch-icon.png">), value: "https://site.com/apple-touch-icon.png"}
|
24
|
+
SiteTests << {html: %(<link rel="shortcut icon" href="http://example.com/myicon.ico" />), value: "http://example.com/myicon.ico"}
|
25
|
+
SiteTests << {html: %(<link rel="icon" href="http://example.com/image.ico" />), value: "http://example.com/image.ico"}
|
26
|
+
SiteTests << {html: %(<link rel="icon" type="image/vnd.microsoft.icon" href="http://example.com/image.ico" />), value: "http://example.com/image.ico"}
|
27
|
+
SiteTests << {html: %(<link rel="icon" type="image/png" href="http://example.com/image.png" />), value: "http://example.com/image.png"}
|
28
|
+
SiteTests << {html: %(<link rel="icon" type="image/gif" href="http://example.com/image.gif" />), value: "http://example.com/image.gif"}
|
29
|
+
SiteTests << {html: %(<link rel="icon" type="image/x-icon" href="http://example.com/image.ico"/>), value: "http://example.com/image.ico"}
|
30
|
+
SiteTests << {html: %(<link rel="shortcut icon" href="https://fbstatic-a.akamaihd.net/rsrc.php/yl/r/H3nktOa7ZMg.ico" />), value: "https://fbstatic-a.akamaihd.net/rsrc.php/yl/r/H3nktOa7ZMg.ico"}
|
31
|
+
SiteTests << {html: %(<link rel="icon" type="image/vnd.microsoft.icon" href="/viconline/img/favicon.ico?1393375504" />), value: "https://site.com/viconline/img/favicon.ico?1393375504"}
|
32
|
+
SiteTests << {html: %(<link rel="shortcut icon" type="image/x-icon" href="/viconline/img/favicon.ico?1393375504" />), value: "https://site.com/viconline/img/favicon.ico?1393375504"}
|
33
|
+
SiteTests << {html: %(<meta name="msapplication-TileImage" content="/win8-tile-144.png"/><meta name="msapplication-TileColor" content="#00aced"/>), value: "https://site.com/win8-tile-144.png"}
|
34
|
+
|
35
|
+
PageTests = []
|
36
|
+
PageTests << {html: %(<meta property="og:image" content="https://www.facebook.com/images/fb_icon_325x325.png" />), value: "https://www.facebook.com/images/fb_icon_325x325.png"}
|
37
37
|
|
38
38
|
class FiconTest < Minitest::Test
|
39
|
-
ENV[
|
39
|
+
ENV["FICON_DB"] = File.join(File.dirname(__FILE__), "test.db")
|
40
40
|
def test_html_chunks
|
41
41
|
SiteTests.each do |t|
|
42
|
-
result = Ficon.site_images(
|
43
|
-
assert result&.url == t[:value], "Seaching |#{t[:html]}| expected #{t[:value]}, got #{result}"
|
42
|
+
result = Ficon.site_images("https://site.com", Nokogiri::HTML(t[:html]))[0]
|
43
|
+
assert result&.url == t[:value], "Seaching |#{t[:html]}| expected #{t[:value]}, got #{result}"
|
44
44
|
end
|
45
45
|
PageTests.each do |t|
|
46
|
-
result = Ficon.page_images(
|
47
|
-
assert result&.url == t[:value], "Seaching |#{t[:html]}| expected #{t[:value]}, got #{result}"
|
46
|
+
result = Ficon.page_images("https://site.com", Nokogiri::HTML(t[:html]))[0]
|
47
|
+
assert result&.url == t[:value], "Seaching |#{t[:html]}| expected #{t[:value]}, got #{result}"
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
51
|
def test_tile_color_extraction
|
52
|
-
html = %
|
53
|
-
result = Ficon.site_images(
|
54
|
-
assert_equal
|
55
|
-
assert_equal
|
52
|
+
html = %(<meta name="msapplication-TileImage" content="/win8-tile-144.png"/><meta name="msapplication-TileColor" content="#00aced"/>)
|
53
|
+
result = Ficon.site_images("https://site.com", Nokogiri::HTML(html))[0]
|
54
|
+
assert_equal "https://site.com/win8-tile-144.png", result.url
|
55
|
+
assert_equal "#00aced", result.tile_color
|
56
56
|
end
|
57
57
|
|
58
58
|
def test_custom_user_agent
|
59
59
|
# Test default user agent
|
60
|
-
ficon_default = Ficon.new(
|
60
|
+
ficon_default = Ficon.new("https://example.com")
|
61
61
|
assert_match(/^FiconBot\/0\.\d+/, ficon_default.user_agent)
|
62
|
-
|
62
|
+
|
63
63
|
# Test custom user agent
|
64
|
-
custom_agent =
|
65
|
-
ficon_custom = Ficon.new(
|
64
|
+
custom_agent = "MyApp/1.0 (Custom Bot)"
|
65
|
+
ficon_custom = Ficon.new("https://example.com", user_agent: custom_agent)
|
66
66
|
assert_equal custom_agent, ficon_custom.user_agent
|
67
|
-
|
67
|
+
|
68
68
|
# Test user agent can be changed after initialization
|
69
|
-
ficon_custom.user_agent =
|
70
|
-
assert_equal
|
69
|
+
ficon_custom.user_agent = "Changed/2.0"
|
70
|
+
assert_equal "Changed/2.0", ficon_custom.user_agent
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_response_status_classification
|
74
|
+
ficon = Ficon.new("https://example.com")
|
75
|
+
|
76
|
+
# Test ALIVE status (2xx)
|
77
|
+
assert_equal Ficon::ALIVE, ficon.classify_response_status(mock_response(200))
|
78
|
+
assert_equal Ficon::ALIVE, ficon.classify_response_status(mock_response(201))
|
79
|
+
assert_equal Ficon::ALIVE, ficon.classify_response_status(mock_response(299))
|
80
|
+
|
81
|
+
# Test DEAD status (404, 410)
|
82
|
+
assert_equal Ficon::DEAD, ficon.classify_response_status(mock_response(404))
|
83
|
+
assert_equal Ficon::DEAD, ficon.classify_response_status(mock_response(410))
|
84
|
+
|
85
|
+
# Test BLOCKED status (401, 403, 429)
|
86
|
+
assert_equal Ficon::BLOCKED, ficon.classify_response_status(mock_response(401))
|
87
|
+
assert_equal Ficon::BLOCKED, ficon.classify_response_status(mock_response(403))
|
88
|
+
assert_equal Ficon::BLOCKED, ficon.classify_response_status(mock_response(429))
|
89
|
+
|
90
|
+
# Test SICK status (5xx and others)
|
91
|
+
assert_equal Ficon::SICK, ficon.classify_response_status(mock_response(500))
|
92
|
+
assert_equal Ficon::SICK, ficon.classify_response_status(mock_response(502))
|
93
|
+
assert_equal Ficon::SICK, ficon.classify_response_status(mock_response(503))
|
94
|
+
assert_equal Ficon::SICK, ficon.classify_response_status(mock_response(300)) # Other codes default to SICK
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_exception_status_classification
|
98
|
+
ficon = Ficon.new("https://example.com")
|
99
|
+
|
100
|
+
# Test DEAD status (DNS and resolution errors)
|
101
|
+
assert_equal Ficon::DEAD, ficon.classify_exception_status(SocketError.new)
|
102
|
+
assert_equal Ficon::DEAD, ficon.classify_exception_status(Resolv::ResolvError.new)
|
103
|
+
|
104
|
+
# Test SICK status (network and timeout errors)
|
105
|
+
assert_equal Ficon::SICK, ficon.classify_exception_status(Timeout::Error.new)
|
106
|
+
assert_equal Ficon::SICK, ficon.classify_exception_status(Errno::ECONNREFUSED.new)
|
107
|
+
assert_equal Ficon::SICK, ficon.classify_exception_status(OpenSSL::SSL::SSLError.new)
|
108
|
+
assert_equal Ficon::SICK, ficon.classify_exception_status(Net::HTTPError.new("error", nil))
|
109
|
+
|
110
|
+
# Test default to SICK for unknown exceptions
|
111
|
+
assert_equal Ficon::SICK, ficon.classify_exception_status(StandardError.new)
|
112
|
+
end
|
113
|
+
|
114
|
+
def test_http_to_https_fallback_conditions
|
115
|
+
# Test that localhost URLs are not converted to HTTPS
|
116
|
+
ficon_localhost = Ficon.allocate
|
117
|
+
uri_localhost = URI("http://localhost:3000/test")
|
118
|
+
|
119
|
+
# Mock the fetch_url method to simulate HTTP failure
|
120
|
+
def ficon_localhost.fetch_url(uri, redirect_limit = 5)
|
121
|
+
if uri.scheme == "http" && !uri.to_s.include?("://localhost") && !uri.host.match?(/^\d+\.\d+\.\d+\.\d+$/)
|
122
|
+
# This should not be reached for localhost
|
123
|
+
raise "Should not attempt HTTPS fallback for localhost"
|
124
|
+
end
|
125
|
+
nil
|
126
|
+
end
|
127
|
+
|
128
|
+
# This should not raise an exception
|
129
|
+
result = ficon_localhost.send(:fetch_url, uri_localhost)
|
130
|
+
assert_nil result
|
131
|
+
|
132
|
+
# Test that IP addresses are not converted to HTTPS
|
133
|
+
ficon_ip = Ficon.allocate
|
134
|
+
uri_ip = URI("http://192.168.1.1/test")
|
135
|
+
|
136
|
+
def ficon_ip.fetch_url(uri, redirect_limit = 5)
|
137
|
+
if uri.scheme == "http" && !uri.to_s.include?("://localhost") && !uri.host.match?(/^\d+\.\d+\.\d+\.\d+$/)
|
138
|
+
# This should not be reached for IP addresses
|
139
|
+
raise "Should not attempt HTTPS fallback for IP addresses"
|
140
|
+
end
|
141
|
+
nil
|
142
|
+
end
|
143
|
+
|
144
|
+
# This should not raise an exception
|
145
|
+
result = ficon_ip.send(:fetch_url, uri_ip)
|
146
|
+
assert_nil result
|
147
|
+
end
|
148
|
+
|
149
|
+
def test_https_port_conversion
|
150
|
+
# Test that port 80 is converted to 443 when switching to HTTPS
|
151
|
+
http_uri = URI("http://example.com:80/test")
|
152
|
+
assert_equal 80, http_uri.port
|
153
|
+
|
154
|
+
https_uri = http_uri.dup
|
155
|
+
https_uri.scheme = "https"
|
156
|
+
https_uri.port = 443 if https_uri.port == 80
|
157
|
+
|
158
|
+
assert_equal "https", https_uri.scheme
|
159
|
+
assert_equal 443, https_uri.port
|
160
|
+
|
161
|
+
# Test that custom ports are preserved
|
162
|
+
http_custom_uri = URI("http://example.com:8080/test")
|
163
|
+
https_custom_uri = http_custom_uri.dup
|
164
|
+
https_custom_uri.scheme = "https"
|
165
|
+
https_custom_uri.port = 443 if https_custom_uri.port == 80
|
166
|
+
|
167
|
+
assert_equal "https", https_custom_uri.scheme
|
168
|
+
assert_equal 8080, https_custom_uri.port # Should remain unchanged
|
169
|
+
end
|
170
|
+
|
171
|
+
private
|
172
|
+
|
173
|
+
def mock_response(code)
|
174
|
+
response = Object.new
|
175
|
+
response.define_singleton_method(:code) { code }
|
176
|
+
response
|
71
177
|
end
|
72
178
|
end
|