Class: Crossbar::HTTP::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/crossbar-http/client.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(url, key: nil, secret: nil, verbose: false, pre_serialize: nil) ⇒ Client

Initializes the client

Parameters:

  • url (String)
    • The url of the router’s HTTP bridge

  • key (String) (defaults to: nil)
    • The key (optional)

  • secret (String) (defaults to: nil)
    • The secret (optional)

  • verbose (Bool) (defaults to: false)
    • ‘True’ if you want debug messages printed

  • pre_serialize (lambda) (defaults to: nil)
    • Lambda to format the data



44
45
46
47
48
49
50
51
52
53
54
# File 'lib/crossbar-http/client.rb', line 44

def initialize(url, key: nil, secret: nil, verbose: false, pre_serialize: nil)

  raise 'The url can not be nil' unless url != nil

  self.url = url
  self.key = key
  self.secret = secret
  self.verbose = verbose
  self.pre_serialize = pre_serialize
  self.sequence = 1
end

Instance Attribute Details

#keyObject

Returns the value of attribute key.



36
37
38
# File 'lib/crossbar-http/client.rb', line 36

def key
  @key
end

#pre_serializeObject

Returns the value of attribute pre_serialize.



36
37
38
# File 'lib/crossbar-http/client.rb', line 36

def pre_serialize
  @pre_serialize
end

#secretObject

Returns the value of attribute secret.



36
37
38
# File 'lib/crossbar-http/client.rb', line 36

def secret
  @secret
end

#sequenceObject

Returns the value of attribute sequence.



36
37
38
# File 'lib/crossbar-http/client.rb', line 36

def sequence
  @sequence
end

#urlObject

Returns the value of attribute url.



36
37
38
# File 'lib/crossbar-http/client.rb', line 36

def url
  @url
end

#verboseObject

Returns the value of attribute verbose.



36
37
38
# File 'lib/crossbar-http/client.rb', line 36

def verbose
  @verbose
end

Class Method Details

._get_nonceObject



133
134
135
# File 'lib/crossbar-http/client.rb', line 133

def self._get_nonce
  rand(0..2**53)
end

._get_timestampObject



129
130
131
# File 'lib/crossbar-http/client.rb', line 129

def self._get_timestamp
  Time.now.utc.strftime('%Y-%m-%dT%H:%M:%S.%LZ')
end

Instance Method Details

#_api_call(uri, body = nil) ⇒ Hash

This method makes tha API call. It is a class method so it can be more easily stubbed for testing

Parameters:

  • uri (URI)

    The uri of the request

  • body (String) (defaults to: nil)

    The body of the request

Returns:

  • (Hash)

    The response from the server



181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# File 'lib/crossbar-http/client.rb', line 181

def _api_call(uri, body=nil)
  # Create the request
  res = Net::HTTP.start(uri.hostname, uri.port, :use_ssl => uri.scheme == 'https') do |http|
    req = Net::HTTP::Post.new(uri)
    req['Content-Type'] = 'application/json'
    req.body = body

    http.request(req)
  end

  case res
    when Net::HTTPSuccess
      puts "Crossbar::HTTP - Response Body: #{res.body}" if self.verbose
      return JSON.parse(res.body, {:symbolize_names => true})
    else
      raise "Crossbar::HTTP - Code: #{res.code}, Error: #{res.message}"
  end
end

#_compute_signature(body) ⇒ signature, ...

Parameters:

  • body (Hash)

Returns:

  • (signature, nonce, timestamp)


113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/crossbar-http/client.rb', line 113

def _compute_signature(body)
  timestamp = self.class._get_timestamp
  nonce = self.class._get_nonce

  # Compute signature: HMAC[SHA256]_{secret} (key | timestamp | seq | nonce | body) => signature
  hm = OpenSSL::HMAC.new(self.secret, OpenSSL::Digest::SHA256.new)
  hm << self.key
  hm << timestamp
  hm << self.sequence.to_s
  hm << nonce.to_s
  hm << body
  signature = Base64.urlsafe_encode64(hm.digest)

  return signature, nonce, timestamp
end

#_make_api_call(json_params = nil) ⇒ Hash

Performs the API call

Parameters:

  • json_params (Hash, nil) (defaults to: nil)

    The parameters that will make up the body of the request

Returns:

  • (Hash)

    The response from the server



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/crossbar-http/client.rb', line 140

def _make_api_call(json_params=nil)

  puts "Crossbar::HTTP - Request: POST #{url}" if self.verbose

  encoded_params = nil
  if json_params != nil
    if self.pre_serialize != nil and self.pre_serialize.is_a? Proc
      json_params = self._parse_params json_params
    end
    encoded_params = JSON.generate(json_params)
  end

  puts "Crossbar::HTTP - Params: #{encoded_params}" if encoded_params != nil and self.verbose

  uri = URI(self.url)

  if self.key != nil and self.secret != nil and encoded_params != nil
    signature, nonce, timestamp = self._compute_signature(encoded_params)
    params = {
        timestamp: timestamp,
        seq: self.sequence.to_s,
        nonce: nonce,
        signature: signature,
        key: self.key
    }
    uri.query = URI.encode_www_form(params)

    puts "Crossbar::HTTP - Signature Params: #{params}" if self.verbose
  end

  # TODO: Not sure what this is supposed to be but this works
  self.sequence += 1

  self._api_call uri, encoded_params
end

#_parse_params(params) ⇒ Object

Parses the params to pre-serialize the overrides



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/crossbar-http/client.rb', line 89

def _parse_params(params)

  if params.is_a? Hash
    return_value = {}
    params.each do |key, value|
      return_value[key] = self._parse_params(value)
    end
  elsif params.is_a? Array
    return_value = []
    params.each_index {|i|
      return_value.push(self._parse_params (params[i]))
    }
  else
    return_value = self.pre_serialize.call(params) || params
  end

  return_value
end

#call(procedure, *args, **kwargs) ⇒ Integer

Calls the procedure

Parameters:

  • procedure (String)
    • The name of the topic

  • *args
    • The arguments and key word arguments

Returns:

  • (Integer)
    • Returns the id of the publish



76
77
78
79
80
81
82
83
84
85
86
# File 'lib/crossbar-http/client.rb', line 76

def call(procedure, *args, **kwargs)
  raise 'The topic can not be nil' unless url != nil

  params = {
      procedure: procedure,
      args: args,
      kwargs: kwargs
  }

  self._make_api_call(params)
end

#publish(topic, *args, **kwargs) ⇒ Integer

Publishes to the topic

Parameters:

  • topic (String)
    • The name of the topic

  • *args
    • The arguments and key word arguments

Returns:

  • (Integer)
    • Returns the id of the publish



60
61
62
63
64
65
66
67
68
69
70
# File 'lib/crossbar-http/client.rb', line 60

def publish(topic, *args, **kwargs)
  raise 'The topic can not be nil' unless url != nil

  params = {
      topic: topic,
      args: args,
      kwargs: kwargs
  }

  self._make_api_call(params)
end