@@ -107,11 +107,33 @@ def register_formatter_methods formatter,
107107 #
108108 attr_accessor :default_encoder_name
109109
110+ ##
111+ # Analyze a Rack environment hash and determine whether it is _probably_
112+ # a CloudEvent. This is done by examining headers only, and does not read
113+ # or parse the request body. The result is a best guess: false negatives or
114+ # false positives are possible for edge cases, but the logic should
115+ # generally detect canonically-formatted events.
116+ #
117+ # @param env [Hash] The Rack environment.
118+ # @return [boolean] Whether the request is likely a CloudEvent.
119+ #
120+ def probable_event? env
121+ return true if env [ "HTTP_CE_SPECVERSION" ]
122+ content_type = ContentType . new env [ "CONTENT_TYPE" ] . to_s
123+ content_type . media_type == "application" &&
124+ [ "cloudevents" , "cloudevents-batch" ] . include? ( content_type . subtype_base )
125+ end
126+
110127 ##
111128 # Decode an event from the given Rack environment hash. Following the
112129 # CloudEvents spec, this chooses a handler based on the Content-Type of
113130 # the request.
114131 #
132+ # Note that this method will read the body (i.e. `rack.input`) stream.
133+ # If you need to access the body after calling this method, you will need
134+ # to rewind the stream. To determine whether the request is a CloudEvent
135+ # without reading the body, use {#probable_event?}.
136+ #
115137 # @param env [Hash] The Rack environment.
116138 # @param allow_opaque [boolean] If true, returns opaque event objects if
117139 # the input is not in a recognized format. If false, raises
@@ -203,6 +225,7 @@ def decode_rack_env env, **format_args
203225 content_type_string = env [ "CONTENT_TYPE" ]
204226 content_type = ContentType . new content_type_string if content_type_string
205227 content = read_with_charset env [ "rack.input" ] , content_type &.charset
228+ env [ "rack.input" ] . rewind rescue nil
206229 decode_binary_content ( content , content_type , env , legacy_data_decode : true ) ||
207230 decode_structured_content ( content , content_type , false , **format_args )
208231 end
0 commit comments