Class: Hyperion::AdminMiddleware
- Inherits:
-
Object
- Object
- Hyperion::AdminMiddleware
- Defined in:
- lib/hyperion/admin_middleware.rb
Overview
Rack middleware that exposes administrative endpoints on the same listener as the application. Disabled by default — only mounted when ‘admin_token` is configured. Currently provides:
POST /-/quit → triggers graceful master drain (SIGTERM to ppid)
GET /-/metrics → returns Hyperion.stats in Prometheus text format
Auth: the request must include ‘X-Hyperion-Admin-Token: <token>`. Mismatch → 401. Path/method mismatch → falls through to the app (so the app can still own /-/anything if Hyperion’s admin is off). When the token is unset, the constructor refuses to wrap — callers must skip mounting this middleware at all.
SECURITY: the bearer token is defense-in-depth, not a substitute for network isolation. Operators MUST keep the listener on a private network or behind TLS + an authenticating reverse proxy. Anyone who can reach the listener AND knows the token can drain the server or scrape its metrics. See docs/REVERSE_PROXY.md for nginx/ALB recipes that block /-/* at the edge.
Constant Summary collapse
- PATH_QUIT =
'/-/quit'- PATH_METRICS =
'/-/metrics'- METRICS_CONTENT_TYPE =
'text/plain; version=0.0.4; charset=utf-8'- JSON_CONTENT_TYPE =
'application/json'- UNAUTHORIZED_BODY =
%({"error":"unauthorized"}\n)
Instance Method Summary collapse
- #call(env) ⇒ Object
-
#initialize(app, token:, signal_target: nil) ⇒ AdminMiddleware
constructor
A new instance of AdminMiddleware.
Constructor Details
#initialize(app, token:, signal_target: nil) ⇒ AdminMiddleware
Returns a new instance of AdminMiddleware.
34 35 36 37 38 39 40 41 42 |
# File 'lib/hyperion/admin_middleware.rb', line 34 def initialize(app, token:, signal_target: nil) raise ArgumentError, 'admin_token must be a non-empty String' if token.nil? || token.to_s.empty? @app = app @token = token.to_s # Override hook for tests. Defaults to ppid in worker context, pid # for single-worker context (caller decides). @signal_target = signal_target end |
Instance Method Details
#call(env) ⇒ Object
44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/hyperion/admin_middleware.rb', line 44 def call(env) path = env['PATH_INFO'] method = env['REQUEST_METHOD'] if path == PATH_QUIT && method == 'POST' (env) { handle_quit(env) } elsif path == PATH_METRICS && method == 'GET' (env) { handle_metrics } else @app.call(env) end end |