Class: Hitch::RackFormGuard

Inherits:
Object
  • Object
show all
Defined in:
lib/hitch/rack_form_guard.rb

Overview

Rack::MethodOverride parses every form POST before Rails dispatches a controller. Hitch's OAuth endpoints and final MCP endpoint own stricter raw body parsers, so pre-populate Rack's form cache only when Rails resolves the request to one of those actions. Resolving ownership matters: Rails accepts format/trailing-slash variants, host routes may shadow the engine, and the MCP controller/route remain host-owned.

Constant Summary collapse

ENDPOINTS =
{
  "hitch/authorizations" => "create",
  "hitch/registrations" => "create",
  "hitch/revocations" => "create",
  "hitch/tokens" => "create",
  "hitch/device_authorizations" => "create",
  "hitch/activations" => "create"
}.freeze
OAUTH_CANDIDATE_PATH =

/activate is anchored to the root: the /oauth/* names are distinctive enough to probe as suffixes under any mount, but bare "activate" is a common host member-action name, and the engine's well-known routes already require a root mount.

%r{/oauth/(?:authorize|register|revoke|token|device_authorization)(?:\.[^/]*)?/?\z|\A/+activate(?:\.[^/]*)?/?\z}

Instance Method Summary collapse

Constructor Details

#initialize(app, routes: -> { Rails.application.routes }) ⇒ RackFormGuard

Returns a new instance of RackFormGuard.



29
30
31
32
# File 'lib/hitch/rack_form_guard.rb', line 29

def initialize(app, routes: -> { Rails.application.routes })
  @app = app
  @routes = routes
end

Instance Method Details

#call(environment) ⇒ Object



34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/hitch/rack_form_guard.rb', line 34

def call(environment)
  route_type = hitch_strict_body_route(environment)
  if route_type
    environment[Rack::RACK_REQUEST_FORM_HASH] = {}
    environment[Rack::RACK_REQUEST_FORM_PAIRS] = []
    # The MCP route is permanently POST/OPTIONS. A generic Rack method
    # override must neither parse its body nor turn authenticated POST
    # traffic into an unauthenticated OPTIONS request.
    environment.delete("HTTP_X_HTTP_METHOD_OVERRIDE") if route_type == :mcp
  end

  @app.call(environment)
end