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
Example:
transip = Transip.new(:username => 'api_username', :ip => '12.34.12.3', :key => mykey, :mode => 'readwrite') # use this in production
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/transip/client.rb', line 34 def initialize( = {}) @key = [:key] || ([:key_file] && File.read([:key_file])) @username = [:username] @ip = [:ip] @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 } # 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.
194 195 196 |
# File 'lib/transip/client.rb', line 194 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.
189 190 191 |
# File 'lib/transip/client.rb', line 189 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.
178 179 180 181 182 183 184 185 |
# File 'lib/transip/client.rb', line 178 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
70 71 72 73 74 75 76 |
# File 'lib/transip/client.rb', line 70 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
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
# File 'lib/transip/client.rb', line 159 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
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 |
# File 'lib/transip/client.rb', line 199 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
222 223 224 225 |
# File 'lib/transip/client.rb', line 222 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)
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 |
# File 'lib/transip/client.rb', line 230 def request(action, = nil) formatted_action = action.to_s.lower_camelcase 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
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/transip/client.rb', line 85 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!
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/transip/client.rb', line 121 def signature(method, parameters, time, nonce) formatted_method = method.to_s.lower_camelcase 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
152 153 154 155 156 |
# File 'lib/transip/client.rb', line 152 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.
56 57 58 59 |
# File 'lib/transip/client.rb', line 56 def turn_off_debugging! @savon_options[:log] = false # disable logging @savon_options[:log_level] = :info # changing the log level end |
#urlencode(input) ⇒ Object
78 79 80 81 82 83 |
# File 'lib/transip/client.rb', line 78 def urlencode(input) output = URI.encode_www_form_component(input) output.gsub!('+', '%20') output.gsub!('%7E', '~') output end |
#use_with_rails! ⇒ Object
Make Savon log to Rails.logger and turn_off_debugging!
62 63 64 65 66 67 |
# File 'lib/transip/client.rb', line 62 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 |