From e6806b9c489dc2807df66c934022948cc4bbb793 Mon Sep 17 00:00:00 2001 From: Aleksandr Starovojtov <37301326+AS-AlStar@users.noreply.github.com> Date: Wed, 31 Jul 2024 20:52:06 +0300 Subject: [PATCH] Added new options error_wrapper for client options (#21) --- README.md | 3 +++ lib/ezclient/client.rb | 1 + lib/ezclient/request.rb | 6 +++++- spec/ezclient_spec.rb | 20 ++++++++++++++++++++ 4 files changed, 29 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8f5499d..ab02d5f 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,7 @@ Valid client options are: - `ssl_context` – ssl context for requests (an `OpenSSL::SSL::SSLContext` instance) - `timeout` – timeout for requests in seconds or hash like `{ read: 5, write: 5, connect: 1 }` - `follow` – enable following redirects (`true` or hash with options – e.g. `{ max_hops: 1, strict: false}`) +- `error_wrapper` – callback called on request exception, makes it possible to handle any error, default behavior: `raise error` All these options are passed to each request made by this client but can be overriden on per-request basis. @@ -91,6 +92,7 @@ You can provide `on_complete`, `on_error` and `on_retry` callbacks like this: on_complete = -> (request, response, metadata) { ... } on_error = -> (request, error, metadata) { ... } on_retry = -> (request, error, metadata) { ... } +error_wrapper = -> (request, error, metadata) { raise error } client = EzClient.new( on_complete: on_complete, @@ -98,6 +100,7 @@ client = EzClient.new( on_retry: on_retry, retry_exceptions: [StandardError], max_retries: 2, + error_wrapper: error_wrapper ) response = client.perform!(:get, url, metadata: :hello) diff --git a/lib/ezclient/client.rb b/lib/ezclient/client.rb index bb2ed7d..3e86280 100644 --- a/lib/ezclient/client.rb +++ b/lib/ezclient/client.rb @@ -15,6 +15,7 @@ class EzClient::Client ssl_context timeout follow + error_wrapper ].freeze def initialize(options = {}) diff --git a/lib/ezclient/request.rb b/lib/ezclient/request.rb index 35ab5e4..ee28885 100644 --- a/lib/ezclient/request.rb +++ b/lib/ezclient/request.rb @@ -28,7 +28,7 @@ def perform end rescue => error on_error.call(self, error, options[:metadata]) - raise error + error_wrapper.call(self, error, options[:metadata]) end def perform! @@ -174,6 +174,10 @@ def follow options[:follow].is_a?(Hash) ? options[:follow] : {} end + def error_wrapper + options[:error_wrapper] || proc { |_request, error, _metadata| raise error } + end + def prepare_headers(headers) headers = HTTP::Headers.coerce(headers) headers[:user_agent] ||= "ezclient/#{EzClient::VERSION}" diff --git a/spec/ezclient_spec.rb b/spec/ezclient_spec.rb index 10c08dc..bfd291a 100644 --- a/spec/ezclient_spec.rb +++ b/spec/ezclient_spec.rb @@ -271,6 +271,26 @@ def self.sign!(*); end expect(calls.size).to eq(1) end end + + context "when error_wrapper callback is provided" do + let(:client_options) { { error_wrapper: error_wrapper } } + let(:calls) { [] } + + let(:error_wrapper) do + proc do |request, error, _metadata| + expect(request.url).to eq("http://example.com") + expect(request.elapsed_seconds).to be_a(Float) + expect(error).to be_a(StandardError) + calls << nil + raise "Wrapped some error" + end + end + + it "calls the error_wrapper callback" do + expect { request.perform }.to raise_error("Wrapped some error") + expect(calls.size).to eq(1) + end + end end context "when connection exception occurs" do