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.
Instance Method Summary collapse
- #active? ⇒ Boolean
- #connect! ⇒ Object
-
#delete(path, &block) ⇒ Object
Send a DELETE request to
path
on the Sunstone Server via Sunstone#send_request. - #disconnect! ⇒ Object
-
#get(path, params = '', &block) ⇒ Object
Send a GET request to
path
on the Sunstone Server via Sunstone#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
path
on the Sunstone Server via Sunstone#send_request. -
#put(path, body = nil, *valid_response_codes, &block) ⇒ Object
Send a PUT request to
path
on the Sunstone Server via Sunstone#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-Key` header -
:user_agent
- An optional string. Will be joined with otherUser-Agent info.
21 22 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 |
# File 'lib/sunstone/connection.rb', line 21 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.
7 8 9 |
# File 'lib/sunstone/connection.rb', line 7 def api_key @api_key end |
#host ⇒ Object (readonly)
Returns the value of attribute host.
7 8 9 |
# File 'lib/sunstone/connection.rb', line 7 def host @host end |
#port ⇒ Object (readonly)
Returns the value of attribute port.
7 8 9 |
# File 'lib/sunstone/connection.rb', line 7 def port @port end |
#prefix ⇒ Object (readonly)
Returns the value of attribute prefix.
7 8 9 |
# File 'lib/sunstone/connection.rb', line 7 def prefix @prefix end |
#use_ssl ⇒ Object (readonly)
Returns the value of attribute use_ssl.
7 8 9 |
# File 'lib/sunstone/connection.rb', line 7 def use_ssl @use_ssl end |
Instance Method Details
#active? ⇒ Boolean
67 68 69 |
# File 'lib/sunstone/connection.rb', line 67 def active? @connection.active? end |
#connect! ⇒ Object
63 64 65 |
# File 'lib/sunstone/connection.rb', line 63 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
- Thepath
on the server to POST to. -
block
- Optional, See Sunstone#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
362 363 364 365 366 |
# File 'lib/sunstone/connection.rb', line 362 def delete(path, &block) request = Net::HTTP::Delete.new(path) send_request(request, nil, &block) end |
#disconnect! ⇒ Object
76 77 78 |
# File 'lib/sunstone/connection.rb', line 76 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
- Thepath
on the server to GET to. -
params
- Either a String, Hash, or Ruby Object that responds to#to_param. Appended on the URL as query params
-
block
- An optional block to call with theNet::HTTPResponse
object.
- 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', {:query => 'stuff'}) # => #<Net::HTTP::Response>
Sunstone.get('/404') # => raises Sunstone::Exception::NotFound
Sunstone.get('/act') do |response|
# ...
end
263 264 265 266 267 268 |
# File 'lib/sunstone/connection.rb', line 263 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
59 60 61 |
# File 'lib/sunstone/connection.rb', line 59 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
- Thepath
on the server to POST to. -
body
- Optional, See Sunstone#send_request. -
block
- Optional, See Sunstone#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', #<IO Object>) # => #<Net::HTTP::Response>
Sunstone.post('/example', {:example => 'data'}) # => #<Net::HTTP::Response>
Sunstone.post('/404') # => raises Sunstone::Exception::NotFound
Sunstone.post('/act') do |response|
# ...
end
299 300 301 302 303 |
# File 'lib/sunstone/connection.rb', line 299 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
- Thepath
on the server to POST to. -
body
- Optional, See Sunstone#send_request. -
block
- Optional, See Sunstone#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', #<IO Object>) # => #<Net::HTTP::Response>
Sunstone.put('/example', {:example => 'data'}) # => #<Net::HTTP::Response>
Sunstone.put('/404') # => raises Sunstone::Exception::NotFound
Sunstone.put('/act') do |response|
# ...
end
334 335 336 337 338 |
# File 'lib/sunstone/connection.rb', line 334 def put(path, body=nil, *valid_response_codes, &block) request = Net::HTTP::Put.new(path) send_request(request, body, &block) end |
#reconnect! ⇒ Object
71 72 73 74 |
# File 'lib/sunstone/connection.rb', line 71 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 server -
body
- Optional, a String, IO Object, or a Ruby object which isconverted into JSON and sent as the body
-
block
- An optional block to call with theNet::HTTPResponse
object.
- 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
130 131 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 |
# File 'lib/sunstone/connection.rb', line 130 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
368 369 370 |
# File 'lib/sunstone/connection.rb', line 368 def server_config @server_config ||= JSON.parse(get('/config').body, symbolize_names: true) end |
#url(path = nil) ⇒ Object
91 92 93 |
# File 'lib/sunstone/connection.rb', line 91 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”
82 83 84 85 86 87 88 89 |
# File 'lib/sunstone/connection.rb', line 82 def user_agent [ @user_agent, "Sunstone/#{Sunstone::VERSION}", "Ruby/#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}", RUBY_PLATFORM ].compact.join(' ') end |