Class: Sunstone::Connection
- Inherits:
-
Object
- Object
- Sunstone::Connection
- Defined in:
- lib/sunstone/connection.rb
Instance Attribute Summary collapse
-
#api_key ⇒ Object
readonly
Returns the value of attribute api_key.
-
#host ⇒ Object
readonly
Returns the value of attribute host.
-
#port ⇒ Object
readonly
Returns the value of attribute port.
-
#prefix ⇒ Object
readonly
Returns the value of attribute prefix.
-
#use_ssl ⇒ Object
readonly
Returns the value of attribute use_ssl.
Class Method Summary collapse
Instance Method Summary collapse
- #active? ⇒ Boolean
- #connect! ⇒ Object
-
#delete(path, &block) ⇒ Object
Send a DELETE request to
pathon the Sunstone Server viaSunstone#send_request. - #disconnect! ⇒ Object
-
#get(path, params = '', &block) ⇒ Object
Send a GET request to
pathon the Sunstone Server viaSunstone#send_request. -
#initialize(config) ⇒ Connection
constructor
Initialize a connection a Sunstone API server.
-
#ping ⇒ Object
Ping the Sunstone.
-
#post(path, body = nil, &block) ⇒ Object
Send a POST request to
pathon the Sunstone Server viaSunstone#send_request. -
#put(path, body = nil, *valid_response_codes, &block) ⇒ Object
Send a PUT request to
pathon the Sunstone Server viaSunstone#send_request. - #reconnect! ⇒ Object
-
#send_request(request, body = nil, &block) ⇒ Object
Sends a Net::HTTPRequest to the server.
- #server_config ⇒ Object
- #url(path = nil) ⇒ Object
-
#user_agent ⇒ Object
Returns the User-Agent of the client.
Constructor Details
#initialize(config) ⇒ Connection
Initialize a connection a Sunstone API server.
Options:
- :url - An optional url used to set the protocol, host, port, and api_key
- :host - The default is to connect to 127.0.0.1.
- :port - Defaults to 80.
- :use_ssl - Defaults to false.
- :api_key - An optional token to send in the
Api-Keyheader - :user_agent - An optional string. Will be joined with other User-Agent info.
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/sunstone/connection.rb', line 23 def initialize(config) if config[:url] uri = URI.parse(config.delete(:url)) config[:api_key] ||= (uri.user ? CGI.unescape(uri.user) : nil) config[:host] ||= uri.host config[:port] ||= uri.port config[:use_ssl] ||= (uri.scheme == 'https') end [:api_key, :host, :port, :use_ssl, :user_agent].each do |key| self.instance_variable_set(:"@#{key}", config[key]) end @connection = Net::HTTP.new(host, port || (use_ssl ? 443 : 80)) @connection.max_retries = 0 @connection.open_timeout = 5 @connection.read_timeout = 30 @connection.write_timeout = 5 @connection.ssl_timeout = 5 @connection.keep_alive_timeout = 30 @connection.use_ssl = use_ssl if use_ssl && config[:ca_cert] @connection.cert_store = OpenSSL::X509::Store.new @connection.cert_store.add_cert(OpenSSL::X509::Certificate.new(File.read(config[:ca_cert]))) end true end |
Instance Attribute Details
#api_key ⇒ Object (readonly)
Returns the value of attribute api_key.
9 10 11 |
# File 'lib/sunstone/connection.rb', line 9 def api_key @api_key end |
#host ⇒ Object (readonly)
Returns the value of attribute host.
9 10 11 |
# File 'lib/sunstone/connection.rb', line 9 def host @host end |
#port ⇒ Object (readonly)
Returns the value of attribute port.
9 10 11 |
# File 'lib/sunstone/connection.rb', line 9 def port @port end |
#prefix ⇒ Object (readonly)
Returns the value of attribute prefix.
9 10 11 |
# File 'lib/sunstone/connection.rb', line 9 def prefix @prefix end |
#use_ssl ⇒ Object (readonly)
Returns the value of attribute use_ssl.
9 10 11 |
# File 'lib/sunstone/connection.rb', line 9 def use_ssl @use_ssl end |
Class Method Details
.use_cookie_store(store) ⇒ Object
439 440 441 |
# File 'lib/sunstone/connection.rb', line 439 def self.(store) Thread.current[:sunstone_cookie_store] = store end |
.with_cookie_store(store) ⇒ Object
443 444 445 446 447 448 |
# File 'lib/sunstone/connection.rb', line 443 def self.(store) Thread.current[:sunstone_cookie_store] = store yield ensure Thread.current[:sunstone_cookie_store] = nil end |
Instance Method Details
#active? ⇒ Boolean
69 70 71 |
# File 'lib/sunstone/connection.rb', line 69 def active? @connection.active? end |
#connect! ⇒ Object
65 66 67 |
# File 'lib/sunstone/connection.rb', line 65 def connect! @connection.start end |
#delete(path, &block) ⇒ Object
Send a DELETE request to path on the Sunstone Server via Sunstone#send_request.
See Sunstone#send_request for more details on how the response is handled
- Paramaters
path- Thepathon the server to POST to.block- Optional, SeeSunstone#send_request
- Return Value
See Sunstone#send_request
Examples:
#!ruby Sunstone.delete('/example') # => #Net::HTTP::Response
Sunstone.delete('/404') # => raises Sunstone::Exception::NotFound
Sunstone.delete('/act') do |response|
...
end
364 365 366 367 368 |
# File 'lib/sunstone/connection.rb', line 364 def delete(path, &block) request = Net::HTTP::Delete.new(path) send_request(request, nil, &block) end |
#disconnect! ⇒ Object
78 79 80 |
# File 'lib/sunstone/connection.rb', line 78 def disconnect! @connection.finish if @connection.active? end |
#get(path, params = '', &block) ⇒ Object
Send a GET request to path on the Sunstone Server via Sunstone#send_request.
See Sunstone#send_request for more details on how the response is handled.
- Paramaters
path- Thepathon the server to GET to.params- Either a String, Hash, or Ruby Object that responds to #to_param. Appended on the URL as query paramsblock- An optional block to call with theNet::HTTPResponseobject.
- Return Value
See Sunstone#send_request
Examples:
#!ruby Sunstone.get('/example') # => #Net::HTTP::Response
Sunstone.get('/example', 'query=stuff') # => #Net::HTTP::Response
Sunstone.get('/example', => 'stuff') # => #Net::HTTP::Response
Sunstone.get('/404') # => raises Sunstone::Exception::NotFound
Sunstone.get('/act') do |response|
...
end
265 266 267 268 269 270 |
# File 'lib/sunstone/connection.rb', line 265 def get(path, params='', &block) params ||= '' request = Net::HTTP::Get.new(path + '?' + params.to_param) send_request(request, nil, &block) end |
#ping ⇒ Object
Ping the Sunstone. If everything is configured and operating correctly "pong" will be returned. Otherwise and Sunstone::Exception should be thrown.
#!ruby Sunstone.ping # => "pong"
Sunstone.ping # raises Sunstone::Exception::ServiceUnavailable if a 503 is returned
61 62 63 |
# File 'lib/sunstone/connection.rb', line 61 def ping get('/ping').body end |
#post(path, body = nil, &block) ⇒ Object
Send a POST request to path on the Sunstone Server via Sunstone#send_request.
See Sunstone#send_request for more details on how the response is handled.
- Paramaters
path- Thepathon the server to POST to.body- Optional, SeeSunstone#send_request.block- Optional, SeeSunstone#send_request
- Return Value
See Sunstone#send_request
Examples:
#!ruby Sunstone.post('/example') # => #Net::HTTP::Response
Sunstone.post('/example', 'body') # => #Net::HTTP::Response
Sunstone.post('/example', #
Sunstone.post('/example', => 'data') # => #Net::HTTP::Response
Sunstone.post('/404') # => raises Sunstone::Exception::NotFound
Sunstone.post('/act') do |response|
...
end
301 302 303 304 305 |
# File 'lib/sunstone/connection.rb', line 301 def post(path, body=nil, &block) request = Net::HTTP::Post.new(path) send_request(request, body, &block) end |
#put(path, body = nil, *valid_response_codes, &block) ⇒ Object
Send a PUT request to path on the Sunstone Server via Sunstone#send_request.
See Sunstone#send_request for more details on how the response is handled.
- Paramaters
path- Thepathon the server to POST to.body- Optional, SeeSunstone#send_request.block- Optional, SeeSunstone#send_request
- Return Value
See Sunstone#send_request
Examples:
#!ruby Sunstone.put('/example') # => #Net::HTTP::Response
Sunstone.put('/example', 'body') # => #Net::HTTP::Response
Sunstone.put('/example', #
Sunstone.put('/example', => 'data') # => #Net::HTTP::Response
Sunstone.put('/404') # => raises Sunstone::Exception::NotFound
Sunstone.put('/act') do |response|
...
end
336 337 338 339 340 |
# File 'lib/sunstone/connection.rb', line 336 def put(path, body=nil, *valid_response_codes, &block) request = Net::HTTP::Put.new(path) send_request(request, body, &block) end |
#reconnect! ⇒ Object
73 74 75 76 |
# File 'lib/sunstone/connection.rb', line 73 def reconnect! disconnect! connect! end |
#send_request(request, body = nil, &block) ⇒ Object
Sends a Net::HTTPRequest to the server. The headers returned from Sunestone#headers are automatically added to the request. The appropriate error is raised if the response is not in the 200..299 range.
- Paramaters
request- A Net::HTTPRequest to send to the serverbody- Optional, a String, IO Object, or a Ruby object which is converted into JSON and sent as the bodyblock- An optional block to call with theNet::HTTPResponseobject.
- Return Value
Returns the return value of the &block if given, otherwise the response object (a Net::HTTPResponse)
Examples:
#!ruby Sunstone.send_request(#Net::HTTP::Get) # => #Net::HTTP::Response
Sunstone.send_request(#<Net::HTTP::Get @path="/404">) # => raises Sunstone::Exception::NotFound
this will still raise an exception if the response_code is not valid
and the block will not be called
Sunstone.send_request(#Net::HTTP::Get) do |response|
...
end
The following example shows how to stream a response:
Sunstone.send_request(#Net::HTTP::Get) do |response| response.read_body do |chunk| io.write(chunk) end end
132 133 134 135 136 137 138 139 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 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 |
# File 'lib/sunstone/connection.rb', line 132 def send_request(request, body=nil, &block) if request.method != 'GET' && Thread.current[:sunstone_transaction_count] if Thread.current[:sunstone_transaction_count] == 1 && !Thread.current[:sunstone_request_sent] Thread.current[:sunstone_request_sent] = request elsif Thread.current[:sunstone_request_sent] = <<~MSG Cannot send multiple request in a transaction. Trying to send: MSG path_and_query = request.path.split('?', 2) << " #{request.method} #{path_and_query[0]}" if path_and_query[1] if request['Query-Encoding'] == 'application/msgpack' << " " << MessagePack.unpack(CGI.unescape(path_and_query[1])).inspect else << " " << CGI.unescape(path_and_query[1]) end end << "\n\nAlready sent:\n" path_and_query = Thread.current[:sunstone_request_sent].path.split('?', 2) << " #{Thread.current[:sunstone_request_sent].method} #{path_and_query[0]}" if path_and_query[1] if request['Query-Encoding'] == 'application/msgpack' << " " << MessagePack.unpack(CGI.unescape(path_and_query[1])) else << " " << CGI.unescape(path_and_query[1]) end end raise ActiveRecord::StatementInvalid, else log_mess = request.path.split('?', 2) = if request['Query-Encoding'] == 'application/msgpack' <<~MSG Cannot send multiple request in a transaction. Trying to send: #{request.method} #{log_mess[0]} #{(log_mess[1] && !log_mess[1].empty?) ? MessagePack.unpack(CGI.unescape(log_mess[1])) : '' } MSG else <<~MSG Cannot send multiple request in a transaction. Trying to send: #{request.method} #{log_mess[0]} #{(log_mess[1] && !log_mess[1].empty?) ? CGI.unescape(log_mess[1]) : '' } MSG end raise ActiveRecord::StatementInvalid, end end request_uri = url(request.path) request_headers.each { |k, v| request[k] = v } request['Content-Type'] ||= 'application/json' if Thread.current[:sunstone_cookie_store] request['Cookie'] = Thread.current[:sunstone_cookie_store].(request_uri) end if body.is_a?(IO) request['Transfer-Encoding'] = 'chunked' request.body_stream = body elsif body.is_a?(String) request.body = body elsif body request.body = JSON.generate(body) end return_value = nil begin close_connection = false @connection.request(request) do |response| if response['Deprecation-Notice'] ::ActiveRecord.deprecator.warn(response['Deprecation-Notice']) end validate_response_code(response) # Get the cookies response.each_header do |key, value| case key.downcase when 'set-cookie' if Thread.current[:sunstone_cookie_store] Thread.current[:sunstone_cookie_store].(request_uri, value) end when 'connection' close_connection = (value == 'close') end end if block_given? return_value = yield(response) else return_value = response end end @connection.finish if close_connection end return_value end |
#server_config ⇒ Object
370 371 372 |
# File 'lib/sunstone/connection.rb', line 370 def server_config @server_config ||= JSON.parse(get('/config').body, symbolize_names: true) end |
#url(path = nil) ⇒ Object
93 94 95 |
# File 'lib/sunstone/connection.rb', line 93 def url(path=nil) "http#{use_ssl ? 's' : ''}://#{host}#{port != 80 ? (port == 443 && use_ssl ? '' : ":#{port}") : ''}#{path}" end |
#user_agent ⇒ Object
Returns the User-Agent of the client. Defaults to: "sunstone-ruby/SUNSTONE_VERSION RUBY_VERSION-pPATCH_LEVEL PLATFORM"
84 85 86 87 88 89 90 91 |
# File 'lib/sunstone/connection.rb', line 84 def user_agent [ @user_agent, "Sunstone/#{Sunstone::VERSION}", "Ruby/#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}", RUBY_PLATFORM ].compact.join(' ') end |