Class: Hyperb::Request

Inherits:
Object
  • Object
show all
Defined in:
lib/hyperb/request.rb

Overview

wraps all requests, performing aws4 signature

Constant Summary collapse

FMT =
'%Y%m%dT%H%M%SZ'.freeze
VERSION =
'v1.23'.freeze
SERVICE =
'hyper'.freeze
ALGORITHM =
'HYPER-HMAC-SHA256'.freeze
KEYPARTS_REQUEST =
'hyper_request'.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(client, path, query = {}, verb = 'GET', body = '', optional_headers = {}) ⇒ Request

Returns a new instance of Request.



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/hyperb/request.rb', line 21

def initialize(client, path, query = {}, verb = 'GET', body = '', optional_headers = {})
  @client = client
  @path = VERSION + path
  @query = URI.encode_www_form(query)
  @body = body.empty? ? body : body.to_json
  @hashed_body = hexdigest(@body)
  @verb = verb.upcase
  @date = Time.now.utc.strftime(FMT)

  set_base_url

  @headers = {
    content_type: 'application/json',
    x_hyper_date: @date,
    host: @host,
    x_hyper_content_sha256: @hashed_body
  }
  @headers.merge!(optional_headers) unless optional_headers.empty?
  @signed = false
end

Instance Attribute Details

#clientObject

Returns the value of attribute client.



19
20
21
# File 'lib/hyperb/request.rb', line 19

def client
  @client
end

#dateObject

Returns the value of attribute date.



19
20
21
# File 'lib/hyperb/request.rb', line 19

def date
  @date
end

#headersObject

Returns the value of attribute headers.



19
20
21
# File 'lib/hyperb/request.rb', line 19

def headers
  @headers
end

#pathObject

Returns the value of attribute path.



19
20
21
# File 'lib/hyperb/request.rb', line 19

def path
  @path
end

#signedObject

Returns the value of attribute signed.



19
20
21
# File 'lib/hyperb/request.rb', line 19

def signed
  @signed
end

#verbObject

Returns the value of attribute verb.



19
20
21
# File 'lib/hyperb/request.rb', line 19

def verb
  @verb
end

Instance Method Details

#canonical_headersObject

sorts all headers, join them by ‘:`, and re-join by n ie: content-type:applicationnhost:us-west-1.hyper.sh



72
73
74
75
76
77
# File 'lib/hyperb/request.rb', line 72

def canonical_headers
  canonical = @headers.sort.map do |header, value|
    "#{header.to_s.tr('_', '-')}:#{value}"
  end
  canonical.join("\n") + "\n"
end

#canonical_requestObject



103
104
105
106
107
108
109
110
111
112
# File 'lib/hyperb/request.rb', line 103

def canonical_request
  [
    @verb,
    @path,
    @query,
    canonical_headers,
    signed_headers,
    @hashed_body
  ].join("\n")
end

#credential_scopeObject



114
115
116
117
118
119
120
121
# File 'lib/hyperb/request.rb', line 114

def credential_scope
  [
    @date[0, 8],
    'us-west-1',
    SERVICE,
    KEYPARTS_REQUEST
  ].join("/") # rubocop:disable StringLiterals
end

#fail_or_return(code, body) ⇒ Object

Raises:

  • (error)


56
57
58
59
60
# File 'lib/hyperb/request.rb', line 56

def fail_or_return(code, body)
  error = Hyperb::Error::ERRORS[code]
  raise(error.new(body, code)) if error
  body
end

#hexdigest(value) ⇒ Object



123
124
125
# File 'lib/hyperb/request.rb', line 123

def hexdigest(value)
  Digest::SHA256.new.update(value).hexdigest
end

#hexhmac(key, value) ⇒ Object



131
132
133
# File 'lib/hyperb/request.rb', line 131

def hexhmac(key, value)
  OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), key, value)
end

#hmac(key, value) ⇒ Object



127
128
129
# File 'lib/hyperb/request.rb', line 127

def hmac(key, value)
  OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha256'), key, value)
end

#performObject



47
48
49
50
51
52
53
54
# File 'lib/hyperb/request.rb', line 47

def perform
  sign unless signed
  final = @base_url + @path + '?' + @query
  options = {}
  options[:body] = @body unless @body.empty?
  response = HTTP.headers(@headers).public_send(@verb.downcase.to_sym, final, options)
  fail_or_return(response.code, response.body)
end

#set_base_urlObject



42
43
44
45
# File 'lib/hyperb/request.rb', line 42

def set_base_url
  @host = "#{client.region}.hyper.sh".freeze
  @base_url = "https://#{@host}/".freeze
end

#signObject

creates Authoriatization header



80
81
82
83
84
85
86
87
# File 'lib/hyperb/request.rb', line 80

def sign
  credential = "#{@client.access_key}/#{credential_scope}"
  auth = "#{ALGORITHM} Credential=#{credential}, "
  auth += "SignedHeaders=#{signed_headers}, "
  auth += "Signature=#{signature}"
  @headers[:authorization] = auth
  @signed = true
end

#signatureObject



91
92
93
94
95
96
97
# File 'lib/hyperb/request.rb', line 91

def signature
  k_date = hmac('HYPER' + @client.secret_key, @date[0, 8])
  k_region = hmac(k_date, 'us-west-1')
  k_service = hmac(k_region, SERVICE)
  k_credentials = hmac(k_service, KEYPARTS_REQUEST)
  hexhmac(k_credentials, string_to_sign)
end

#signed_headersObject

join all headers by ‘;` ie: content-type;x-hyper-hmac-sha256



65
66
67
# File 'lib/hyperb/request.rb', line 65

def signed_headers
  @headers.keys.sort.map { |header| header.to_s.tr('_', '-') }.join(';')
end

#string_to_signObject



99
100
101
# File 'lib/hyperb/request.rb', line 99

def string_to_sign
  [ALGORITHM, @date, credential_scope, hexdigest(canonical_request)].join("\n")
end