Class: SecApi::Middleware::ErrorHandler

Inherits:
Faraday::Middleware
  • Object
show all
Defined in:
lib/sec_api/middleware/error_handler.rb

Overview

Faraday middleware that converts HTTP status codes and Faraday exceptions into typed SecApi exceptions.

This middleware maps:

  • HTTP 400 → ValidationError (permanent)

  • HTTP 401 → AuthenticationError (permanent)

  • HTTP 403 → AuthenticationError (permanent)

  • HTTP 404 → NotFoundError (permanent)

  • HTTP 422 → ValidationError (permanent)

  • HTTP 429 → RateLimitError (transient)

  • HTTP 5xx → ServerError (transient)

  • Faraday::TimeoutError → NetworkError (transient)

  • Faraday::ConnectionFailed → NetworkError (transient)

  • Faraday::SSLError → NetworkError (transient)

Position in middleware stack: After retry/rate limiter, before adapter

Raises:

  • when API returns 400 (Bad Request) or 422 (Unprocessable Entity)

  • when API returns 401 (Unauthorized) or 403 (Forbidden)

  • when API returns 404 (Not Found)

  • when API returns 429 (Too Many Requests)

  • when API returns 5xx (Server Error)

  • when network issues occur (timeout, connection failure, SSL error)

Instance Method Summary collapse

Constructor Details

#initialize(app, options = {}) ⇒ ErrorHandler

Initializes the error handler middleware.

Parameters:

  • The next middleware in the stack

  • (defaults to: {})

    Configuration options

Options Hash (options):

  • :config (SecApi::Config)

    The config object containing on_error callback



46
47
48
49
# File 'lib/sec_api/middleware/error_handler.rb', line 46

def initialize(app, options = {})
  super(app)
  @config = options[:config]
end

Instance Method Details

#call(env) ⇒ Faraday::Response

Processes the request and converts HTTP errors to typed exceptions.

Parameters:

  • The request/response environment

Returns:

  • The response (if no error)

Raises:

  • when API returns 400 or 422

  • when API returns 401 or 403

  • when API returns 404

  • when API returns 429

  • when API returns 5xx

  • when network issues occur



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/sec_api/middleware/error_handler.rb', line 62

def call(env)
  response = @app.call(env)
  handle_response(response.env)
  response
rescue Faraday::RetriableResponse => e
  # Faraday retry raises this to signal a retry - we need to re-raise it
  # so retry middleware can catch it
  raise e
rescue Faraday::TimeoutError => e
  # Don't invoke on_error here - TransientErrors will be retried.
  # on_error is invoked by Instrumentation middleware after all retries exhausted.
  raise NetworkError.new(
    "Request timeout. " \
    "Check network connectivity or increase request_timeout in configuration. " \
    "Original error: #{e.message}.",
    request_id: env[:request_id]
  )
rescue Faraday::ConnectionFailed => e
  # Don't invoke on_error here - TransientErrors will be retried.
  # on_error is invoked by Instrumentation middleware after all retries exhausted.
  raise NetworkError.new(
    "Connection failed: #{e.message}. " \
    "Verify network connectivity and sec-api.io availability. " \
    "This is a temporary issue that will be retried automatically.",
    request_id: env[:request_id]
  )
rescue Faraday::SSLError => e
  # Don't invoke on_error here - TransientErrors will be retried.
  # on_error is invoked by Instrumentation middleware after all retries exhausted.
  raise NetworkError.new(
    "SSL/TLS error: #{e.message}. " \
    "This may indicate certificate validation issues or secure connection problems. " \
    "Verify your system's SSL certificates are up to date.",
    request_id: env[:request_id]
  )
end