Class: RailsAiBridge::HttpTransportApp
- Inherits:
-
Object
- Object
- RailsAiBridge::HttpTransportApp
- Defined in:
- lib/rails_ai_bridge/http_transport_app.rb
Overview
Builds the Rack endpoint used by both standalone HTTP mode and the middleware auto-mount path so request handling stays in one place.
Class Method Summary collapse
-
.build(transport:, path:) ⇒ Proc
Rack-compatible app.
Class Method Details
.build(transport:, path:) ⇒ Proc
Returns rack-compatible app.
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/rails_ai_bridge/http_transport_app.rb', line 11 def build(transport:, path:) mcp_cfg = RailsAiBridge.configuration.mcp max_reqs = mcp_cfg.effective_http_rate_limit_max_requests window_sec = mcp_cfg.effective_http_rate_limit_window_seconds limiter = mcp_cfg.rate_limiter || build_default_rate_limiter(max_requests: max_reqs, window_seconds: window_sec) cors_origins = Array(mcp_cfg.cors_origins).reject(&:empty?) lambda do |env| return [404, { 'Content-Type' => 'application/json' }, ['{"error":"Not found"}']] unless [path, "#{path}/"].include?(env['PATH_INFO']) request = Rack::Request.new(env) cors_headers = build_cors_headers(request.get_header('HTTP_ORIGIN'), cors_origins) return [204, cors_headers, ['']] if request.request_method == 'OPTIONS' && cors_headers if mcp_cfg.require_http_auth && !Mcp::Authenticator.any_configured? Mcp::HttpStructuredLog.emit(request: request, event: :unauthorized, http_status: 401) return Mcp::Authenticator. end auth_result = Mcp::Authenticator.call(request) unless auth_result.success? Mcp::HttpStructuredLog.emit(request: request, event: :unauthorized, http_status: 401) return Mcp::Authenticator. end = RailsAiBridge.configuration.mcp. if begin = .call(auth_result.context, request) rescue StandardError => error Rails.logger.error("rails_ai_bridge: authorize lambda raised #{error.class}: #{error.}") if defined?(Rails) && Rails.logger Mcp::HttpStructuredLog.emit(request: request, event: :forbidden, http_status: 403) return [403, { 'Content-Type' => 'application/json' }, ['{"error":"Forbidden"}']] end unless Rails.logger.warn("rails_ai_bridge: authorize lambda denied access for #{request.ip} at #{request.path}") if defined?(Rails) && Rails.logger Mcp::HttpStructuredLog.emit(request: request, event: :forbidden, http_status: 403) return [403, { 'Content-Type' => 'application/json' }, ['{"error":"Forbidden"}']] end end if limiter && !rate_limiter_allow?(limiter, request) Instrumentation.instrument('rate_limit.hit', ip: request.ip, path: request.path) Mcp::HttpStructuredLog.emit(request: request, event: :rate_limited, http_status: 429) return [429, { 'Content-Type' => 'application/json', 'Retry-After' => window_sec.to_s }, ['{"error":"Too many requests"}']] end response = transport.handle_request(request) Mcp::HttpStructuredLog.emit(request: request, event: :handled, http_status: response.first) response[1].merge!(cors_headers) if cors_headers response end end |