Class: Linzer::Message::Adapter::Abstract Abstract

Inherits:
Object
  • Object
show all
Defined in:
lib/linzer/message/adapter/abstract.rb

Overview

This class is abstract.

Subclass and implement #header, #derived, and #field to create a new adapter.

Abstract base class for HTTP message adapters.

Adapters provide a unified interface for accessing HTTP message components regardless of the underlying HTTP library. Each adapter implements field retrieval, header access, and signature attachment for a specific HTTP message type.

Instance Method Summary collapse

Constructor Details

#initialize(operation, **options) ⇒ Abstract

Returns a new instance of Abstract.

Raises:

  • (Error)

    This class cannot be instantiated directly



22
23
24
# File 'lib/linzer/message/adapter/abstract.rb', line 22

def initialize(operation, **options)
  raise Linzer::Error, "Cannot instantiate an abstract class!"
end

Instance Method Details

#[](field) ⇒ String, ...

Retrieves a component value from the message.

Handles both regular header fields and derived components, including parameter processing (‘;sf`, `;bs`, `;req`, `;key`).

Examples:

Header field

adapter["content-type"]  # => "application/json"

Derived component

adapter["@method"]  # => "POST"

With structured field parameter

adapter['"example-dict";key="a"']  # => "1"

Parameters:

  • field (String, FieldId)

    The component identifier

Returns:

  • (String, Integer, nil)

    The component value, or nil if not found



72
73
74
75
76
# File 'lib/linzer/message/adapter/abstract.rb', line 72

def [](field)
  field_id = (field.is_a?(FieldId) || field.is_a?(Field::FastIdentifier)) ? field : parse_field_name(field)
  return nil if field_id.nil? || field_id.item.nil?
  retrieve(field_id.item, field_id.derived? ? :derived : :field)
end

#attach!(signature, additional_headers: {}) ⇒ Object

Attaches a signature to the underlying HTTP message.

Parameters:

  • signature (Signature)

    The signature to attach

  • additional_headers (#each) (defaults to: {})

    Additional headers to attach after signature processing. Header values overwrite existing values with the same field name.

Returns:

  • (Object)

    The underlying HTTP message



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/linzer/message/adapter/abstract.rb', line 105

def attach!(signature, additional_headers: {})
  signature_headers = signature.to_h

  if !has_signature?
    signature_headers.each { |h, v| set_header!(h, v) }
  else
    begin
      signature_headers.each do |hdr, value|
        merged = HTTP::StructuredField.parse_dictionary(String(header(hdr)))
        merged.merge!(HTTP::StructuredField.parse_dictionary(value))
        set_header!(hdr, HTTP::StructuredField.serialize_dictionary(merged))
      end
    rescue Error => ex
      raise Error,
            "Cannot attach signature, invalid signature header(s)!",
            cause: ex
    end
  end

  if !additional_headers.empty?
    additional_headers.each { |h, v| set_header!(h, v) }
  end

  @operation
end

#attached_request?Boolean

Checks if this response has an attached request.

Attached requests enable the ‘;req` parameter for accessing request fields from a response signature.

Returns:

  • (Boolean)

    true if an attached request is present



44
45
46
# File 'lib/linzer/message/adapter/abstract.rb', line 44

def attached_request?
  response? && !!@attached_request
end

#field?(f) ⇒ Boolean

Checks if a component exists in the message.

Parameters:

  • f (String)

    The component identifier

Returns:

  • (Boolean)

    true if the component can be retrieved



52
53
54
# File 'lib/linzer/message/adapter/abstract.rb', line 52

def field?(f)
  !!self[f]
end

#has_signature?Boolean

Checks whether the request contains HTTP Message Signature headers.

Returns true if either the “signature-input” or “signature” header is present.

Returns:

  • (Boolean)

    true if the request includes HTTP Message Signature headers



93
94
95
# File 'lib/linzer/message/adapter/abstract.rb', line 93

def has_signature?
  !!header("signature-input") || !!header("signature")
end

#header(name) ⇒ String?

This method is abstract.

Subclasses must implement this method.

Retrieves a raw header value by name.

Parameters:

  • name (String)

    The header name

Returns:

  • (String, nil)

    The header value

Raises:



83
84
85
# File 'lib/linzer/message/adapter/abstract.rb', line 83

def header(name)
  raise Linzer::Error, "Sub-classes are required to implement this method!"
end

#request?Boolean

Checks if this adapter wraps an HTTP request.

Returns:

  • (Boolean)

    true if the wrapped message is a request



28
29
30
# File 'lib/linzer/message/adapter/abstract.rb', line 28

def request?
  self.class.to_s.include?("Request")
end

#response?Boolean

Checks if this adapter wraps an HTTP response.

Returns:

  • (Boolean)

    true if the wrapped message is a response



34
35
36
# File 'lib/linzer/message/adapter/abstract.rb', line 34

def response?
  self.class.to_s.include?("Response")
end