Class: Dispatch::Rails::ResponseAnnotator

Inherits:
Object
  • Object
show all
Defined in:
lib/dispatch/rails/response_annotator.rb

Overview

Opt-in Rack middleware (config.structured_error_responses). On 4xx/5xx responses it stamps the Rails request id — and, when a report base URL is known, a report URL — into response headers, and optionally into JSON error bodies. This is the API-only analogue of the bug-report widget: it hands the caller a correlation id they can quote when filing a curated report, which the Dispatch server then links back to the auto-captured error.

It is mounted just outside ActionDispatch::ShowExceptions so it sees the FINAL rendered error response — whether the app rescued the error itself (a normal 4xx) or it propagated and ShowExceptions rendered the 500. It never changes the status code, never swallows a propagating exception, and passes through untouched anything it cannot safely parse.

Constant Summary collapse

HEADER_REQUEST_ID =
"X-Dispatch-Request-Id"
HEADER_REPORT_URL =
"X-Dispatch-Report-Url"
BODY_REQUEST_ID =
"dispatch_request_id"
BODY_REPORT_URL =
"dispatch_report_url"

Instance Method Summary collapse

Constructor Details

#initialize(app) ⇒ ResponseAnnotator

Returns a new instance of ResponseAnnotator.



24
25
26
# File 'lib/dispatch/rails/response_annotator.rb', line 24

def initialize(app)
  @app = app
end

Instance Method Details

#call(env) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/dispatch/rails/response_annotator.rb', line 28

def call(env)
  # @app.call is deliberately outside the rescue: if ShowExceptions re-raises
  # (e.g. show_exceptions disabled, or in tests), the exception must keep
  # propagating — we never swallow it.
  status, headers, body = @app.call(env)
  begin
    annotate(env, status, headers, body)
  rescue StandardError => e
    warn "[dispatch-rails] response annotation failed: #{e.class}: #{e.message}"
    [status, headers, body]
  end
end