Skip to content

Commit 96ca015

Browse files
committed
Handle argument errors when http request raises argument error for headers having CR/LF characters
Faraday / ruby cannot parse headers which contain CR/LF characters. As this issue appears to exist deep down in the faraday / ruby stack, we should handle the error rather than letting the application alert. This change attempts to handle only those argument errors that roughly fuzzy match the exception string 'header field value cannot include CR/LF' (with a bit of fuzziness in case the exact message changes) but still raise for other exceptions.
1 parent 5b6bd27 commit 96ca015

File tree

4 files changed

+46
-9
lines changed

4 files changed

+46
-9
lines changed

app/lib/link_checker/uri_checker/http_checker.rb

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ def initialize(options = {})
8989
end
9090
end
9191

92-
class FaradayError < Error
92+
class HttpCommunicationError < Error
9393
def initialize(options = {})
9494
super(suggested_fix: :determine_if_temporary, **options)
9595
end
@@ -238,7 +238,7 @@ def make_request(method, check_ssl: true)
238238
response
239239
rescue Faraday::ConnectionFailed
240240
add_problem(
241-
FaradayError.new(
241+
HttpCommunicationError.new(
242242
summary: :website_unavailable,
243243
message: :website_host_offline,
244244
from_redirect: from_redirect?,
@@ -247,7 +247,7 @@ def make_request(method, check_ssl: true)
247247
nil
248248
rescue Faraday::TimeoutError
249249
add_problem(
250-
FaradayError.new(
250+
HttpCommunicationError.new(
251251
summary: :website_unavailable,
252252
message: :page_is_not_responding,
253253
from_redirect: from_redirect?,
@@ -269,9 +269,26 @@ def make_request(method, check_ssl: true)
269269
make_request(method, check_ssl: false)
270270
rescue Faraday::Error
271271
add_problem(
272-
FaradayError.new(
272+
HttpCommunicationError.new(
273273
summary: :page_unavailable,
274-
message: :page_failing_to_load,
274+
message: :technical_error_on_page,
275+
from_redirect: from_redirect?,
276+
),
277+
)
278+
nil
279+
# Ruby net-http cannot handle responses with headers with CR/LF characters in, and such responses raise
280+
# an argument error. We want to catch these and add to the report for now, rather than continuing to raise these
281+
# as errors, which can trigger alerting. We are planning on raising this to be fixed at the net-http level which may
282+
# mean we do not have to handle these here.
283+
# Doing some fuzzy matching on the error message to try and ensure a bit of resilience, allowing for changes to the
284+
# exact error message in the exception.
285+
rescue ArgumentError => e
286+
raise e unless e.message =~ /(.*)header(.*) CR\/LF/
287+
288+
add_problem(
289+
HttpCommunicationError.new(
290+
summary: :page_unavailable,
291+
message: :technical_error_on_page,
275292
from_redirect: from_redirect?,
276293
),
277294
)

app/lib/link_checker/uri_checker/problem.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def get_string(symbol)
4545
UnusualUrl
4646
NotAvailableOnline
4747
NoHost
48-
FaradayError
48+
HttpCommunicationError
4949
PageNotFound
5050
PageRequiresLogin
5151
PageIsUnavailable

config/locales/en.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,9 @@ en:
103103
singular: This page has a security problem that users may be alerted to.
104104
redirect: This redirects to a page with a security problem.
105105

106-
page_failing_to_load:
107-
singular: This page is failing to load.
108-
redirect: This redirects to a page that isn't loading.
106+
technical_error_on_page:
107+
singular: This page has a technical error.
108+
redirect: This redirects to a page that has a technical error.
109109

110110
determine_if_temporary: Determine if this is a temporary issue or the resource is no longer available.
111111

spec/lib/link_checker_spec.rb

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,26 @@
142142
include_examples "has warnings"
143143
end
144144

145+
context "header with CR/LF character" do
146+
let(:uri) { "http://www.not-gov.uk/header_with_CRLF_character" }
147+
before do
148+
stub_request(:get, uri)
149+
.to_return(headers: { "Invalid" => "A header containing a carriage return \r character" })
150+
end
151+
152+
include_examples "has errors"
153+
include_examples "has a problem summary", "Page unavailable"
154+
end
155+
156+
it "does not recue from other argument error" do
157+
uri = "http://www.not-gov.uk/raises_argument_error"
158+
error = ArgumentError.new("something that's nothing to do with headers and carriage return line feed chars")
159+
160+
stub_request(:get, uri).to_raise(error)
161+
162+
expect { described_class.new(uri).call }.to raise_error(error)
163+
end
164+
145165
context "slow response" do
146166
let(:uri) { "http://www.not-gov.uk/slow_response" }
147167

0 commit comments

Comments
 (0)