Class: Transip::Client
- Inherits:
-
Object
- Object
- Transip::Client
- Defined in:
- lib/transip/client.rb
Direct Known Subclasses
ColocationClient, DomainClient, ForwardClient, VpsClient, WebhostingClient
Constant Summary collapse
- API_VERSION =
'5.0'
- API_SERVICE =
'DomainService'
Instance Attribute Summary collapse
-
#debug ⇒ Object
Returns the value of attribute debug.
-
#hash ⇒ Object
Returns the value of attribute hash.
-
#ip ⇒ Object
Returns the value of attribute ip.
-
#mode ⇒ Object
Returns the value of attribute mode.
-
#password ⇒ Object
Returns the value of attribute password.
-
#response ⇒ Object
readonly
Returns the value of attribute response.
-
#username ⇒ Object
Returns the value of attribute username.
Instance Method Summary collapse
-
#actions ⇒ Object
Returns Array with all possible SOAP WSDL actions.
- #api_service ⇒ Object
- #api_version ⇒ Object
-
#client ⇒ Object
Returns a Savon::Client object to be used in the connection.
-
#client! ⇒ Object
Same as client method but initializes a brand new fresh client.
-
#convert_array_to_hash(array) ⇒ Object
yes, i know, it smells bad.
-
#cookies(method, parameters) ⇒ Object
Used for authentication.
-
#fix_array_definitions(options) ⇒ Object
This makes sure that arrays are properly encoded as soap-arrays by Gyoku.
-
#initialize(options = {}) ⇒ Client
constructor
Options: * username - Your login name on the TransIP website.
-
#process_response(response) ⇒ Object
converts the savon response object to something we can return to the caller - A TransipStruct object - An array of TransipStructs - nil.
-
#request(action, options = nil) ⇒ Object
This is the main request function throws ApiError returns response object (can be TransipStruct or Array of TransipStruct).
- #serialize_parameters(parameters, key_prefix = nil) ⇒ Object
-
#signature(method, parameters, time, nonce) ⇒ Object
does all the techy stuff to calculate transip’s sick authentication scheme: a hash with all the request information is subsequently: serialized like a www form SHA512 digested asn1 header added private key encrypted Base64 encoded URL encoded I think the guys at transip were trying to use their entire crypto-toolbox!.
- #to_cookies(content) ⇒ Object
-
#turn_off_debugging! ⇒ Object
By default we don’t want to debug! Changing might impact other Savon usages.
- #urlencode(input) ⇒ Object
-
#use_with_rails! ⇒ Object
Make Savon log to Rails.logger and turn_off_debugging!.
- #wsdl ⇒ Object
Constructor Details
#initialize(options = {}) ⇒ Client
Options:
-
username - Your login name on the TransIP website.
-
ip - needed in production
-
key / key_file - key is one of your private keys (these can be requested via your Controlpanel). key_file is path to file containing key.
-
mode - :readonly, :readwrite
-
proxy - url of proxy through which you want to route API requests. For example, if you use Quataguard Static on Heroku, use ENV. If not used, leave blank or don’t supply it as a parameter.
Example:
transip = Transip.new(:username => 'api_username', :ip => '12.34.12.3', :key => mykey, :mode => 'readwrite', :proxy => '') # use this in production
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/transip/client.rb', line 35 def initialize( = {}) @key = [:key] || ([:key_file] && File.read([:key_file])) @username = [:username] @ip = [:ip] @proxy = [:proxy] @api_version = [:api_version] @api_service = [:api_service] raise ArgumentError, "The :username, :ip and :key options are required!" if @username.nil? or @key.nil? @mode = [:mode] || :readonly @endpoint = [:endpoint] || 'api.transip.nl' if [:password] @password = [:password] end @savon_options = { :wsdl => wsdl } # if proxy is present, use it if @proxy != nil @savon_options[:proxy] = @proxy end # By default we don't want to debug! self.turn_off_debugging! end |
Instance Attribute Details
#debug ⇒ Object
Returns the value of attribute debug.
24 25 26 |
# File 'lib/transip/client.rb', line 24 def debug @debug end |
#hash ⇒ Object
Returns the value of attribute hash.
8 9 10 |
# File 'lib/transip/client.rb', line 8 def hash @hash end |
#ip ⇒ Object
Returns the value of attribute ip.
8 9 10 |
# File 'lib/transip/client.rb', line 8 def ip @ip end |
#mode ⇒ Object
Returns the value of attribute mode.
8 9 10 |
# File 'lib/transip/client.rb', line 8 def mode @mode end |
#password ⇒ Object
Returns the value of attribute password.
8 9 10 |
# File 'lib/transip/client.rb', line 8 def password @password end |
#response ⇒ Object (readonly)
Returns the value of attribute response.
9 10 11 |
# File 'lib/transip/client.rb', line 9 def response @response end |
#username ⇒ Object
Returns the value of attribute username.
8 9 10 |
# File 'lib/transip/client.rb', line 8 def username @username end |
Instance Method Details
#actions ⇒ Object
Returns Array with all possible SOAP WSDL actions.
202 203 204 |
# File 'lib/transip/client.rb', line 202 def actions client.operations end |
#api_service ⇒ Object
16 17 18 |
# File 'lib/transip/client.rb', line 16 def api_service @api_service || self.class::API_SERVICE end |
#api_version ⇒ Object
11 12 13 14 |
# File 'lib/transip/client.rb', line 11 def api_version # We use self.class:: here to not use parentclass constant. @api_version || self.class::API_VERSION end |
#client ⇒ Object
Returns a Savon::Client object to be used in the connection. This object is re-used and cached as @client.
197 198 199 |
# File 'lib/transip/client.rb', line 197 def client @client ||= client! end |
#client! ⇒ Object
Same as client method but initializes a brand new fresh client. You have to use this one when you want to re-set the mode (readwrite, readonly), or authentication details of your client.
186 187 188 189 190 191 192 193 |
# File 'lib/transip/client.rb', line 186 def client! @client = Savon::Client.new(@savon_options) do namespaces( "xmlns:enc" => "http://schemas.xmlsoap.org/soap/encoding/" ) end return @client end |
#convert_array_to_hash(array) ⇒ Object
yes, i know, it smells bad
77 78 79 80 81 82 83 |
# File 'lib/transip/client.rb', line 77 def convert_array_to_hash(array) result = {} array.each_with_index do |value, index| result[index] = value end result end |
#cookies(method, parameters) ⇒ Object
Used for authentication
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
# File 'lib/transip/client.rb', line 167 def (method, parameters) time = Time.new.to_i #strip out the -'s because transip requires the nonce to be between 6 and 32 chars nonce = SecureRandom.uuid.gsub("-", '') result = [ "login=#{self.username}", "mode=#{self.mode}", "timestamp=#{time}", "nonce=#{nonce}", "clientVersion=#{api_version}", "signature=#{signature(method, parameters, time, nonce)}" ] debug_log("signature:\n#{signature(method, parameters, time, nonce)}") result end |
#fix_array_definitions(options) ⇒ Object
This makes sure that arrays are properly encoded as soap-arrays by Gyoku
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 |
# File 'lib/transip/client.rb', line 207 def fix_array_definitions() result = {} .each do |key, value| if value.is_a?(Array) and (value.size > 0) entry_name = value.first.class.name.split(":").last result[key] = { 'item' => {:content! => value, :'@xsi:type' => "tns:#{entry_name}"}, :'@xsi:type' => "tns:ArrayOf#{entry_name}", :'@enc:arrayType' => "tns:#{entry_name}[#{value.size}]" } elsif value.is_a?(Hash) result[key] = fix_array_definitions(value) else result[key] = value end end result end |
#process_response(response) ⇒ Object
converts the savon response object to something we can return to the caller
-
A TransipStruct object
-
An array of TransipStructs
-
nil
230 231 232 233 |
# File 'lib/transip/client.rb', line 230 def process_response(response) response = response.to_hash.values.first[:return] rescue nil TransipStruct.from_soap(response) end |
#request(action, options = nil) ⇒ Object
This is the main request function throws ApiError returns response object (can be TransipStruct or Array of TransipStruct)
238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 |
# File 'lib/transip/client.rb', line 238 def request(action, = nil) formatted_action = action.to_s.camelize(:lower) parameters = { # for some reason, the transip server wants the body root tag to be # the name of the action. :message_tag => formatted_action } = .to_hash if .is_a?(Transip::TransipStruct) if .is_a?(Hash) = fix_array_definitions() elsif .nil? = nil else raise "Invalid parameter format (should be nil, hash or TransipStruct)" end parameters[:message] = parameters[:cookies] = (action, ) debug_log("parameters:\n#{parameters.inspect}") response = client.call(action, parameters) process_response(response) rescue Savon::SOAPFault => e raise ApiError.new(e), e..sub(/^\(\d+\)\s+/,'') # We raise our own error (FIXME: Correct?). end |
#serialize_parameters(parameters, key_prefix = nil) ⇒ Object
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/transip/client.rb', line 93 def serialize_parameters(parameters, key_prefix=nil) debug_log("serialize_parameters(#{parameters.inspect}, #{key_prefix.inspect}") parameters = parameters.to_hash.values.first if parameters.is_a? TransipStruct parameters = convert_array_to_hash(parameters) if parameters.is_a? Array if not parameters.is_a? Hash return urlencode(parameters) end return "#{key_prefix}=" if parameters.empty? encoded_parameters = [] parameters.each do |key, value| next if key.to_s == '@xsi:type' encoded_key = (key_prefix.nil?) ? urlencode(key) : "#{key_prefix}[#{urlencode(key)}]" if value.is_a?(Hash) or value.is_a?(Array) or value.is_a?(TransipStruct) encoded_parameters << serialize_parameters(value, encoded_key) else encoded_value = urlencode(value) encoded_parameters << "#{encoded_key}=#{encoded_value}" end end encoded_parameters = encoded_parameters.join("&") debug_log("encoded_parameters:\n#{encoded_parameters.split('&').join("\n")}") encoded_parameters end |
#signature(method, parameters, time, nonce) ⇒ Object
does all the techy stuff to calculate transip’s sick authentication scheme: a hash with all the request information is subsequently: serialized like a www form SHA512 digested asn1 header added private key encrypted Base64 encoded URL encoded I think the guys at transip were trying to use their entire crypto-toolbox!
129 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 |
# File 'lib/transip/client.rb', line 129 def signature(method, parameters, time, nonce) formatted_method = method.to_s.camelize(:lower) parameters ||= {} input = convert_array_to_hash(parameters.values) = { '__method' => formatted_method, '__service' => api_service, '__hostname' => @endpoint, '__timestamp' => time, '__nonce' => nonce } input.merge!() raise "Invalid RSA key" unless @key =~ /-----BEGIN (RSA )?PRIVATE KEY-----(.*)-----END (RSA )?PRIVATE KEY-----/sim serialized_input = serialize_parameters(input) digest = Digest::SHA512.new.digest(serialized_input) asn_header = "\x30\x51\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03\x05\x00\x04\x40" # convert asn_header literal to ASCII-8BIT if RUBY_VERSION.split('.')[0] == "2" asn = asn_header.b + digest else asn = asn_header + digest end private_key = OpenSSL::PKey::RSA.new(@key) encrypted_asn = private_key.private_encrypt(asn) readable_encrypted_asn = Base64.encode64(encrypted_asn) urlencode(readable_encrypted_asn) end |
#to_cookies(content) ⇒ Object
160 161 162 163 164 |
# File 'lib/transip/client.rb', line 160 def (content) content.map do |item| HTTPI::Cookie.new item end end |
#turn_off_debugging! ⇒ Object
By default we don’t want to debug! Changing might impact other Savon usages.
63 64 65 66 |
# File 'lib/transip/client.rb', line 63 def turn_off_debugging! @savon_options[:log] = false # disable logging @savon_options[:log_level] = :info # changing the log level end |
#urlencode(input) ⇒ Object
85 86 87 88 89 90 91 |
# File 'lib/transip/client.rb', line 85 def urlencode(input) output = URI.encode_www_form_component(input) output.gsub!('+', '%20') output.gsub!('%7E', '~') output.gsub!('*', '%2A') output end |
#use_with_rails! ⇒ Object
Make Savon log to Rails.logger and turn_off_debugging!
69 70 71 72 73 74 |
# File 'lib/transip/client.rb', line 69 def use_with_rails! if Rails.env.production? self.turn_off_debugging! end @savon_options[:logger] = Rails.logger # using the Rails logger end |
#wsdl ⇒ Object
20 21 22 |
# File 'lib/transip/client.rb', line 20 def wsdl "https://api.transip.nl/wsdl/?service=#{api_service}" end |