Class: Elastomer::Middleware::OpaqueId

Inherits:
Faraday::Middleware
  • Object
show all
Defined in:
lib/elastomer/middleware/opaque_id.rb

Overview

This Faraday middleware implements the “X-Opaque-Id” request / response headers for Elasticsearch. The X-Opaque-Id header, when provided on the request header, will be returned as a header in the response. This is useful in environments which reuse connections to ensure that cross-talk does not occur between two requests.

The SecureRandom lib is used to generate a UUID string for each request. This value is used as the content for the “X-Opaque-Id” header. If the value is different between the request and the response, then an ‘Elastomer::Client::OpaqueIdError` is raised. In this case no response will be returned.

See [Elasticsearch “X-Opaque-Id” header](github.com/elasticsearch/elasticsearch/issues/1202) for more details.

Constant Summary collapse

X_OPAQUE_ID =
"X-Opaque-Id".freeze
COUNTER_MAX =
2**32 - 1

Instance Method Summary collapse

Instance Method Details

#call(env) ⇒ Object

Faraday middleware implementation.

env - Faraday environment Hash

Returns the environment Hash



30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/elastomer/middleware/opaque_id.rb', line 30

def call( env )
  uuid = generate_uuid.freeze
  env[:request_headers][X_OPAQUE_ID] = uuid

  @app.call(env).on_complete do |renv|
    response_uuid = renv[:response_headers][X_OPAQUE_ID]
    if uuid != response_uuid
      raise ::Elastomer::Client::OpaqueIdError,
            "Conflicting 'X-Opaque-Id' headers: request #{uuid.inspect}, response #{response_uuid.inspect}"
    end
  end
end

#generate_uuidObject

Generate a UUID using the built-in SecureRandom class. This can be a little slow at times, so we will reuse the same UUID and append an incrementing counter.

Returns the UUID string.



48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/elastomer/middleware/opaque_id.rb', line 48

def generate_uuid
  t = Thread.current

  unless t.key? :opaque_id_base
    t[:opaque_id_base]    = (SecureRandom.urlsafe_base64(12) + "%08x").freeze
    t[:opaque_id_counter] = -1
  end

  t[:opaque_id_counter] += 1
  t[:opaque_id_counter] = 0 if t[:opaque_id_counter] > COUNTER_MAX
  t[:opaque_id_base] % t[:opaque_id_counter]
end