Skip to content

Commit

Permalink
Make RaiseError middleware configurable to not raise error on certain…
Browse files Browse the repository at this point in the history
… status codes (e.g. 404) (#1590)
  • Loading branch information
clemens authored Sep 13, 2024
1 parent 9e5c8a1 commit 98d5adf
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 27 deletions.
25 changes: 15 additions & 10 deletions docs/middleware/included/raising-errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,23 +63,28 @@ and raised as `Faraday::NilStatusError`, which inherits from `Faraday::ServerErr

The behavior of this middleware can be customized with the following options:

| Option | Default | Description |
|---------------------|---------|-------------|
| **include_request** | true | When true, exceptions are initialized with request information including `method`, `url`, `url_path`, `params`, `headers`, and `body`. |
| Option | Default | Description |
|----------------------|---------|-------------|
| **include_request** | true | When true, exceptions are initialized with request information including `method`, `url`, `url_path`, `params`, `headers`, and `body`. |
| **allowed_statuses** | [] | An array of status codes that should not raise an error. |

### Example Usage

```ruby
conn = Faraday.new(url: 'http://httpbingo.org') do |faraday|
faraday.response :raise_error, include_request: true
faraday.response :raise_error, include_request: true, allowed_statuses: [404]
end

begin
conn.get('/wrong-url') # => Assume this raises a 404 response
rescue Faraday::ResourceNotFound => e
e.response[:status] #=> 404
e.response[:headers] #=> { ... }
e.response[:body] #=> "..."
e.response[:request][:url_path] #=> "/wrong-url"
conn.get('/wrong-url') # => Assume this raises a 404 response
conn.get('/protected-url') # => Assume this raises a 401 response
rescue Faraday::UnauthorizedError => e
e.response[:status] # => 401
e.response[:headers] # => { ... }
e.response[:body] # => "..."
e.response[:request][:url_path] # => "/protected-url"
end
```

In this example, a `Faraday::UnauthorizedError` exception is raised for the `/protected-url` request, while the
`/wrong-url` request does not raise an error because the status code `404` is in the `allowed_statuses` array.
32 changes: 15 additions & 17 deletions lib/faraday/response/raise_error.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,30 @@ class RaiseError < Middleware
# rubocop:disable Naming/ConstantName
ClientErrorStatuses = (400...500)
ServerErrorStatuses = (500...600)
ClientErrorStatusesWithCustomExceptions = {
400 => Faraday::BadRequestError,
401 => Faraday::UnauthorizedError,
403 => Faraday::ForbiddenError,
404 => Faraday::ResourceNotFound,
408 => Faraday::RequestTimeoutError,
409 => Faraday::ConflictError,
422 => Faraday::UnprocessableEntityError,
429 => Faraday::TooManyRequestsError
}.freeze
# rubocop:enable Naming/ConstantName

DEFAULT_OPTIONS = { include_request: true }.freeze
DEFAULT_OPTIONS = { include_request: true, allowed_statuses: [] }.freeze

def on_complete(env)
return if Array(options[:allowed_statuses]).include?(env[:status])

case env[:status]
when 400
raise Faraday::BadRequestError, response_values(env)
when 401
raise Faraday::UnauthorizedError, response_values(env)
when 403
raise Faraday::ForbiddenError, response_values(env)
when 404
raise Faraday::ResourceNotFound, response_values(env)
when *ClientErrorStatusesWithCustomExceptions.keys
raise ClientErrorStatusesWithCustomExceptions[env[:status]], response_values(env)
when 407
# mimic the behavior that we get with proxy requests with HTTPS
msg = %(407 "Proxy Authentication Required")
raise Faraday::ProxyAuthError.new(msg, response_values(env))
when 408
raise Faraday::RequestTimeoutError, response_values(env)
when 409
raise Faraday::ConflictError, response_values(env)
when 422
raise Faraday::UnprocessableEntityError, response_values(env)
when 429
raise Faraday::TooManyRequestsError, response_values(env)
when ClientErrorStatuses
raise Faraday::ClientError, response_values(env)
when ServerErrorStatuses
Expand Down
20 changes: 20 additions & 0 deletions spec/faraday/response/raise_error_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -252,4 +252,24 @@
end
end
end

describe 'allowing certain status codes' do
let(:conn) do
Faraday.new do |b|
b.response :raise_error, allowed_statuses: [404]
b.adapter :test do |stub|
stub.get('bad-request') { [400, { 'X-Reason' => 'because' }, 'keep looking'] }
stub.get('not-found') { [404, { 'X-Reason' => 'because' }, 'keep looking'] }
end
end
end

it 'raises an error for status codes that are not explicitly allowed' do
expect { conn.get('bad-request') }.to raise_error(Faraday::BadRequestError)
end

it 'does not raise an error for allowed status codes' do
expect { conn.get('not-found') }.not_to raise_error
end
end
end

0 comments on commit 98d5adf

Please sign in to comment.