Hoodoo::Client and related software such as Hoodoo::Services::Middleware need common access to information about special processing headers defined by Hoodoo and the Hoodoo API. This class is just a container - pretty much a namespaced library - holding that kind of information and support methods.
UUID_PROPERTY_PROC | = | -> ( value ) { value = Hoodoo::UUID.valid?( value ) && value value || nil # => 'value' if 'value' is truthy, 'nil' if 'value' falsy } |
Used by HEADER_TO_PROPERTY;
this Proc when called with some non-nil value from an HTTP header
representing a UUID, evaluates to either the UUID as a String or |
||
UUID_HEADER_PROC | = | -> ( value ) { value } |
Used by HEADER_TO_PROPERTY; this Proc when called with some UUID evaluates to the input value coerced to a String and no other changes. |
||
KVP_PROPERTY_PROC | = | -> ( value ) { Hash[ URI.decode_www_form( value ) ] } |
Used by HEADER_TO_PROPERTY; this Proc when called with some non-nil value from an HTTP header containing URL-encoded simple key/value pair data returns a decoded Hash of key/value pairs. Use URL encoding in the HTTP header value as per: www.w3.org/TR/html5/forms.html#url-encoded-form-data Invalid input will produce unusual results, e.g. an empty Hash or a Hash where certain keys may have empty string values. |
||
KVP_HEADER_PROC | = | -> ( value ) { URI.encode_www_form( value ) } |
Used by HEADER_TO_PROPERTY; this Proc when called with some non-nested Hash evaluates to a URL-encoded form data String as per: |
||
DATETIME_IN_PAST_ONLY_PROPERTY_PROC | = | -> ( value ) { value = Hoodoo::Utilities.valid_iso8601_subset_datetime?( value ) value = nil if value && Hoodoo::Utilities.is_in_future?( value ) value || nil # => 'value' if 'value' is truthy, 'nil' if 'value' falsy } |
Used by HEADER_TO_PROPERTY;
this Proc when called with some non-nil value from an HTTP header
representing a Date/Time in a supported format, evaluates to either a
parsed DateTime instance or |
||
DATETIME_WRITER_PROC | = | -> ( value ) { Hoodoo::Utilities.rationalise_datetime( value ) } |
Used by HEADER_TO_PROPERTY; this Proc is called with a Time, Date, DateTime or DateTime-parseable String and returns a DateTime. It is used for a custom write accessor for the property associated with a header entry and works independently of the validation mechanism for inbound String-only from-header data. |
||
DATETIME_HEADER_PROC | = | -> ( value ) { Hoodoo::Utilities.nanosecond_iso8601( value ) } |
Used by HEADER_TO_PROPERTY; this Proc when called with a DateTime instance evaluates to a String representing the DateTime as an ISO 8601 subset value given to nanosecond precision. |
||
BOOLEAN_PROPERTY_PROC | = | -> ( value ) { value.to_s.downcase == 'yes' || value == true ? true : false } |
Used by HEADER_TO_PROPERTY;
this Proc when called with some non-nil value from an HTTP header
representing a Boolean as “yes” or “no”, evaluates to either
|
||
BOOLEAN_HEADER_PROC | = | -> ( value ) { value == true ? 'yes' : 'no' } |
Used by HEADER_TO_PROPERTY;
this Proc when called with |
||
HEADER_TO_PROPERTY | = | { # Take care not to define any property name which clashes with an # option in any other part of this entire system where these "other # options" get merged in. A project search for # 'HEADER_TO_PROPERTY' in comments should find those. 'HTTP_X_RESOURCE_UUID' => { :property => :resource_uuid, :property_proc => UUID_PROPERTY_PROC, :header => 'X-Resource-UUID', :header_proc => UUID_HEADER_PROC, :secured => true, }, 'HTTP_X_ASSUME_IDENTITY_OF' => { :property => :assume_identity_of, :property_proc => KVP_PROPERTY_PROC, :header => 'X-Assume-Identity-Of', :header_proc => KVP_HEADER_PROC, :secured => true, :auto_transfer => true, }, 'HTTP_X_DATED_AT' => { :property => :dated_at, :property_proc => DATETIME_IN_PAST_ONLY_PROPERTY_PROC, :writer_proc => DATETIME_WRITER_PROC, :header => 'X-Dated-At', :header_proc => DATETIME_HEADER_PROC, :auto_transfer => true, }, 'HTTP_X_DATED_FROM' => { :property => :dated_from, :property_proc => DATETIME_IN_PAST_ONLY_PROPERTY_PROC, :writer_proc => DATETIME_WRITER_PROC, :header => 'X-Dated-From', :header_proc => DATETIME_HEADER_PROC, :auto_transfer => true, }, 'HTTP_X_DEJA_VU' => { :property => :deja_vu, :property_proc => BOOLEAN_PROPERTY_PROC, :header => 'X-Deja-Vu', :header_proc => BOOLEAN_HEADER_PROC, }, } |
Various “X-Foo”-style HTTP headers specified in the Hoodoo API Specification have special meanings and values for those need to be set up in request data and Hoodoo::Client endpoints. Processing around these is data driven by this mapping Hash. Keys are the HTTP header names in Rack (upper case, “HTTP_”-prefix) format. Values are options bundles as follows:
An additional key of |
Define a series of read and custom write accessors according to the
HTTP_HEADER_OPTIONS_MAP. For example, a property of “dated_at” results in a
dated_at
reader, a dated_at=
writer which calls
Hoodoo::Utilities.rationalise_datetime
to clean up the input value and sets the result into the
@dated_at
instance variable which the read accessor will be
expecting to use.
klass
-
The Class to which the instance methods will be added.
Source: show
# File lib/hoodoo/client/headers.rb, line 233 def self.define_accessors_for_header_equivalents( klass ) klass.class_eval do HEADER_TO_PROPERTY.each do | rack_header, description | attr_reader( description[ :property ] ) custom_writer = description[ :writer_proc ] if custom_writer.nil? attr_writer( description[ :property ] ) else define_method( "#{ description[ :property ] }=" ) do | parameter | instance_variable_set( "@#{ description[ :property ] }", description[ :writer_proc ].call( parameter ) ) result = instance_variable_get("@#{ description[ :property ] }") end end end end end
From a Hash-like source where keys are HTTP header names and values are the corresponding HTTP header values, extract interesting values and return a Hash of options as described below.
Any X-Foo
header is extracted, including core Hoodoo extension headers such as
X-Interaction-ID
, which is present in any response. The “X-”
is stripped, the rest converted to lower case and hyphens converted to
underscores. The interaction ID, therefore, would be set as an
interaction_id
option. X-Foo
would be set as a
foo
option - and so-on.
The header matcher accepts headers from the Hash-like source in upper or
lower case with hyphens or underscores inside; extracted headers can
therefore start with any of X_
, x_
,
X-
or x-
. The Hash-like source must support the
each
operator yielding a key and value to the block on each
iteration.
Header values are not translated at all, so (unless something very unsual is going on) the option values will be Strings.
If the same header is encountered more than once, only the first one encountered (in enumeration order, whatever that might be) is stored.
Parameters:
hashlike_source
-
Hash-like source containing HTTP headers/values.
Source: show
# File lib/hoodoo/client/headers.rb, line 282 def self.x_header_to_options( hashlike_source ) hashlike_source ||= {} options = {} hashlike_source.each do | key, value | next unless ( key[ 0 ] == 'x' || key[ 0 ] == 'X' ) && ( key[ 1 ] == '-' || key[ 1 ] == '_' ) entry = key.to_s.downcase.gsub( '-', '_' )[ 2..-1 ] unless entry == '' || options.has_key?( entry ) options[ entry ] = value end end return options end