|
| 1 | +# frozen_string_literal: true |
| 2 | + |
| 3 | +module Hooks |
| 4 | + module App |
| 5 | + # Builds Rack environment hash for lifecycle hooks and handler processing |
| 6 | + # |
| 7 | + # This class centralizes the construction of the Rack environment that gets |
| 8 | + # passed to lifecycle hooks and handlers, ensuring consistency and making |
| 9 | + # it easy to reference the environment structure. |
| 10 | + # |
| 11 | + # @example Building a Rack environment |
| 12 | + # builder = RackEnvBuilder.new(request, headers, request_context) |
| 13 | + # rack_env = builder.build |
| 14 | + # |
| 15 | + class RackEnvBuilder |
| 16 | + # Initialize the builder with required components |
| 17 | + # |
| 18 | + # @param request [Grape::Request] The Grape request object |
| 19 | + # @param headers [Hash] Request headers hash |
| 20 | + # @param request_context [Hash] Request context containing metadata |
| 21 | + # @option request_context [String] :request_id Unique request identifier |
| 22 | + # @option request_context [String] :handler Handler class name |
| 23 | + # @param endpoint_config [Hash] Endpoint configuration |
| 24 | + # @param start_time [Time] Request start time |
| 25 | + # @param full_path [String] Full request path including root path |
| 26 | + def initialize(request, headers, request_context, endpoint_config, start_time, full_path) |
| 27 | + @request = request |
| 28 | + @headers = headers |
| 29 | + @request_context = request_context |
| 30 | + @endpoint_config = endpoint_config |
| 31 | + @start_time = start_time |
| 32 | + @full_path = full_path |
| 33 | + end |
| 34 | + |
| 35 | + # Build the Rack environment hash |
| 36 | + # |
| 37 | + # Constructs a hash containing standard Rack environment variables |
| 38 | + # plus Hooks-specific extensions for lifecycle hooks and handlers. |
| 39 | + # |
| 40 | + # @return [Hash] Complete Rack environment hash |
| 41 | + def build |
| 42 | + rack_env = build_base_environment |
| 43 | + add_http_headers(rack_env) |
| 44 | + rack_env |
| 45 | + end |
| 46 | + |
| 47 | + private |
| 48 | + |
| 49 | + # Build the base Rack environment with standard and Hooks-specific variables |
| 50 | + # This pretty much creates everything plus the kitchen sink. It will be very rich in information |
| 51 | + # and will be used by lifecycle hooks and handlers to access request metadata. |
| 52 | + # |
| 53 | + # @return [Hash] Base environment hash |
| 54 | + def build_base_environment |
| 55 | + { |
| 56 | + "REQUEST_METHOD" => @request.request_method, |
| 57 | + "PATH_INFO" => @request.path_info, |
| 58 | + "QUERY_STRING" => @request.query_string, |
| 59 | + "HTTP_VERSION" => @request.env["HTTP_VERSION"], |
| 60 | + "REQUEST_URI" => @request.url, |
| 61 | + "SERVER_NAME" => @request.env["SERVER_NAME"], |
| 62 | + "SERVER_PORT" => @request.env["SERVER_PORT"], |
| 63 | + "CONTENT_TYPE" => @request.content_type, |
| 64 | + "CONTENT_LENGTH" => @request.content_length, |
| 65 | + "REMOTE_ADDR" => @request.env["REMOTE_ADDR"], |
| 66 | + "hooks.request_id" => @request_context[:request_id], |
| 67 | + "hooks.handler" => @request_context[:handler], |
| 68 | + "hooks.endpoint_config" => @endpoint_config, |
| 69 | + "hooks.start_time" => @start_time.iso8601, |
| 70 | + "hooks.full_path" => @full_path |
| 71 | + } |
| 72 | + end |
| 73 | + |
| 74 | + # Add HTTP headers to the environment with proper Rack naming convention |
| 75 | + # |
| 76 | + # @param rack_env [Hash] Environment hash to modify |
| 77 | + def add_http_headers(rack_env) |
| 78 | + @headers.each do |key, value| |
| 79 | + env_key = "HTTP_#{key.upcase.tr('-', '_')}" |
| 80 | + rack_env[env_key] = value |
| 81 | + end |
| 82 | + end |
| 83 | + end |
| 84 | + end |
| 85 | +end |
0 commit comments