Skip to content

Endpoints

Alex Woods edited this page Mar 15, 2024 · 3 revisions

Endpoint Provider

An endpoint provider is configurable on generic Config. The EndpointProvider takes service specific endpoint parameters. The EndpointProvider is code generated from the Endpoint Rules. If no Endpoint Rules are present, a default ruleset which returns the static configured Endpoint will be used. The Endpoint rules are an implementation detail.

module Endpoint
  Params = ::Struct.new(
    :endpoint,
    keyword_init: true
  ) do
    include Hearth::Structure
  end

  class Provider
    def resolve_endpoint(params)
      endpoint = params.endpoint

      if (endpoint != nil)
        return Hearth::EndpointRules::Endpoint.new(uri: endpoint)
      end
      raise ArgumentError, "Endpoint is not set - you must configure an endpoint."

    end
  end

Endpoint

The Endpoint holds the URI, auth schemes (list of AuthScheme), and headers.

module EndpointRules
  # An Authentication Scheme supported by an Endpoint
  AuthScheme = ::Struct.new(
    :scheme_id,
    :properties,
    keyword_init: true
  ) do
    def initialize(*)
      super
      self.properties ||= {}
    end
  end

  # An Endpoint resolved by an EndpointProvider
  Endpoint = ::Struct.new(
    :uri,
    :auth_schemes,
    :headers,
    keyword_init: true
  ) do
    def initialize(*)
      super
      self.headers ||= {}
      self.auth_schemes ||= []
    end
  end
end

Endpoint Middleware

The middleware is generic and is responsible for:

  1. Building the endpoint parameters from config, input and context using an operation specific parameter builder
  2. Calling the endpoint provider to resolve the endpoint.
  3. Updating the request. This merges the hostname/path and preserves modeled hostprefix and path from serilaization.
  4. Updating auth properties. See: Endpoints and Auth
module Hearth
  module Middleware

    class Endpoint
      def initialize(
        app, endpoint_provider:, param_builder:, **kwargs
      )
        @app = app
        @param_builder = param_builder
        @endpoint_provider = endpoint_provider
        @config = kwargs
      end

      def call(input, context)
        params = @param_builder.build(@config, input, context)
        endpoint = @endpoint_provider.resolve_endpoint(params)
        update_request(context, endpoint)
        update_auth_properties(context, endpoint.auth_schemes)

        @app.call(input, context)
      end
    end
  end
end

The usage in clients is generated per operation and must include all of the config required to resolve parameters, eg:

stack.use(
  Hearth::Middleware::Endpoint,
  param_builder: Endpoint::Parameters::GetCity, # operation specific parameter builder
  endpoint_provider: config.endpoint_provider, # configured endpoint provider
  endpoint: config.endpoint, # all of the configs required to build parameters
)

Endpoints and Auth

The AuthSchemeResolver is responsible for resolving the Auth Scheme. Endpoint resolution only augments and modifies the resolved auth scheme signer/identity properties - for example, changing the region used for signing in Sigv4.