lib/gds_api/exceptions.rb
module GdsApi # Abstract error class class BaseError < StandardError # Give Sentry extra context about this event # https://docs.sentry.io/clients/ruby/context/ def raven_context { # Make Sentry group exceptions by type instead of message, so all # exceptions like `GdsApi::TimedOutException` will get grouped as one # error and not an error per URL. fingerprint: [self.class.name], } end end class EndpointNotFound < BaseError; end class TimedOutException < BaseError; end class InvalidUrl < BaseError; end # Superclass for all 4XX and 5XX errors class HTTPErrorResponse < BaseError attr_accessor :code, :error_details def initialize(code, message = nil, error_details = nil, request_body = nil) super(message) @code = code @error_details = error_details @request_body = request_body end end # Superclass & fallback for all 4XX errors class HTTPClientError < HTTPErrorResponse; end class HTTPIntermittentClientError < HTTPClientError; end class HTTPNotFound < HTTPClientError; end class HTTPGone < HTTPClientError; end class HTTPPayloadTooLarge < HTTPClientError; end class HTTPUnauthorized < HTTPClientError; end class HTTPForbidden < HTTPClientError; end class HTTPConflict < HTTPClientError; end class HTTPUnprocessableEntity < HTTPClientError; end class HTTPTooManyRequests < HTTPIntermittentClientError; end # Superclass & fallback for all 5XX errors class HTTPServerError < HTTPErrorResponse; end class HTTPIntermittentServerError < HTTPServerError; end class HTTPInternalServerError < HTTPServerError; end class HTTPBadGateway < HTTPIntermittentServerError; end class HTTPUnavailable < HTTPIntermittentServerError; end class HTTPGatewayTimeout < HTTPIntermittentServerError; end module ExceptionHandling def build_specific_http_error(error, url, details = nil, request_body = nil) message = "URL: #{url}\nResponse body:\n#{error.http_body}\n\nRequest body:\n#{request_body}" code = error.http_code error_class_for_code(code).new(code, message, details) end def error_class_for_code(code) case code when 401 GdsApi::HTTPUnauthorized when 403 GdsApi::HTTPForbidden when 404 GdsApi::HTTPNotFound when 409 GdsApi::HTTPConflict when 410 GdsApi::HTTPGone when 413 GdsApi::HTTPPayloadTooLarge when 422 GdsApi::HTTPUnprocessableEntity when 429 GdsApi::HTTPTooManyRequests when (400..499) GdsApi::HTTPClientError when 500 GdsApi::HTTPInternalServerError when 502 GdsApi::HTTPBadGateway when 503 GdsApi::HTTPUnavailable when 504 GdsApi::HTTPGatewayTimeout when (500..599) GdsApi::HTTPServerError else GdsApi::HTTPErrorResponse end end end end