diff --git a/README.md b/README.md index fd6a4ff..131ed51 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,20 @@ Optionally, set a custom user agent to identify your integration client = Frontapp::Client.new(auth_token: 'token', user_agent: 'Eye-Phone Integration (engineering@planet-express.com') ``` +### Errors & Rate Limits + +When the API returns an error, a specific exception is raised (`Frontapp::BadRequestError`, `Frontapp::UnauthorizedError`, `Frontapp::NotFoundError`, `Frontapp::ConflictError`, `Frontapp::TooManyRequestsError`). The response object is accessible on the error for inspecting headers and status: + +```ruby +begin + client.get_contact("ctc_55c8c149") +rescue Frontapp::TooManyRequestsError => e + retry_after = e.response.headers["Retry-After"] + sleep(retry_after.to_i) + retry +end +``` + ### Attachments ```ruby # Download a file attachment @@ -437,3 +451,4 @@ Special thanks to: - [feolea](https://github.com/feolea) - [jefferal1995](https://github.com/jefferal1995) - [panozzaj](https://github.com/panozzaj) +- [joren](https://github.com/joren) diff --git a/lib/frontapp/error.rb b/lib/frontapp/error.rb index db7f2f1..968fce9 100644 --- a/lib/frontapp/error.rb +++ b/lib/frontapp/error.rb @@ -1,5 +1,7 @@ module Frontapp class Error < StandardError + attr_reader :response + def self.from_response(response) error_class = case response.status when 400 then BadRequestError diff --git a/spec/error_spec.rb b/spec/error_spec.rb index 555e96e..6d7c51e 100644 --- a/spec/error_spec.rb +++ b/spec/error_spec.rb @@ -49,4 +49,24 @@ frontapp.get_contact(1) end.to raise_error(Frontapp::TooManyRequestsError) end + + it "exposes response headers on the error" do + stub_request(:get, "#{base_url}/contacts/1"). + with(headers: headers). + to_return( + status: 429, + body: '{"_error":{"message":"Rate limited"}}', + headers: { + "Retry-After" => "17", + "x-ratelimit-remaining" => "0", + } + ) + + frontapp.get_contact(1) + rescue Frontapp::TooManyRequestsError => e + expect(e.response).not_to be_nil + expect(e.response.status).to eq(429) + expect(e.response.headers["Retry-After"]).to eq("17") + expect(e.response.headers["x-ratelimit-remaining"]).to eq("0") + end end