Class: Soaspec::RestHandler
- Inherits:
-
ExchangeHandler
- Object
- ExchangeHandler
- Soaspec::RestHandler
- Extended by:
- RestExchangeFactory, RestParameters
- Includes:
- ResponseExtractor, RestParametersDefaults
- Defined in:
- lib/soaspec/exchange_handlers/rest_handler.rb
Overview
Wraps around Savon client defining default values dependent on the soap request
Instance Attribute Summary collapse
-
#api_username ⇒ Object
User used in making API calls.
Attributes inherited from ExchangeHandler
#exception, #request_option, #template_name
Instance Method Summary collapse
-
#after_response(_response, _self) ⇒ Object
Override this with ‘after_response’ within class definition to perform an action after response is retrieved.
-
#calculated_json_path_matches(path, response, attribute, not_empty: false) ⇒ Array
Calculate all JSON path values based on rules.
-
#found?(response) ⇒ Boolean
@@return [Boolean] Whether the request found the desired value or not.
-
#hash_used_in_request(override_hash) ⇒ Hash
Hash used in REST request based on data conversion.
-
#include_in_body?(response, expected) ⇒ Boolean
Whether response body includes String.
-
#include_key?(response, expected) ⇒ Boolean
Whether response body contains expected key.
-
#include_value?(response, expected) ⇒ Boolean
Whether response contains expected value.
-
#init_merge_options ⇒ Hash
Initialize value of merged options Also called to verify any issues with options on creating object.
-
#initialize(name = self.class.to_s, options = {}) ⇒ RestHandler
constructor
Setup object to handle communicating with a particular SOAP WSDL.
-
#json_path_values_for(response, path, attribute: nil) ⇒ Enumerable
List of values matching JSON path.
-
#make_request(override_parameters) ⇒ RestClient::Response
Used in together with Exchange request that passes such override parameters Following are for the body of the request.
-
#parse_headers ⇒ Hash
Perform ERB on each header value.
-
#request(response) ⇒ RestClient::Request, String
Request of API call.
-
#request_parameters(override_parameters) ⇒ Soaspec::RestRequest
Parameters used in making a request.
-
#response_body(response, format: :hash) ⇒ Object
Generic body to be displayed in error messages.
-
#rest_resource_options ⇒ Hash
Add values to here when extending this class to have default REST options.
-
#status_code_for(response) ⇒ Integer
HTTP Status code for response.
-
#value_from_path(response, path, attribute: nil) ⇒ String
Based on a exchange, return the value at the provided xpath If the path does not begin with a ‘/’, a ‘//’ is added to it.
-
#values_from_path(response, path, attribute: nil) ⇒ Enumerable
List of values returned from path.
-
#xpath_elements_for(response: nil, xpath: nil, attribute: nil) ⇒ Enumerable
Returns the value at the provided xpath.
Methods included from RestParameters
base_url, basic_auth, basic_auth_file, client_id, headers, oauth2, oauth2_file, pascal_keys, retry_on_exceptions
Methods included from RestExchangeFactory
Methods included from RestParametersDefaults
#base_url_value, #parent_url, #pascal_keys?, #rest_client_headers
Methods included from ResponseExtractor
Methods inherited from ExchangeHandler
#default_hash=, #elements, #set_remove_key, #set_remove_keys, #store, #to_s, use, #use
Methods included from HandlerAccessors
#attribute, #convert_to_lower, #default_hash, #element, #mandatory_elements, #mandatory_json_values, #mandatory_xpath_values, #strip_namespaces, #template_name
Methods included from ExchangeHandlerDefaults
#convert_to_lower?, #expected_mandatory_elements, #expected_mandatory_json_values, #expected_mandatory_xpath_values, #retry_exception_limit, #retry_on_exceptions, #retry_pause_time, #strip_namespaces?
Constructor Details
#initialize(name = self.class.to_s, options = {}) ⇒ RestHandler
Setup object to handle communicating with a particular SOAP WSDL
31 32 33 34 35 36 37 38 39 40 41 42 |
# File 'lib/soaspec/exchange_handlers/rest_handler.rb', line 31 def initialize(name = self.class.to_s, = {}) raise "Base URL not set! Please set in class with 'base_url' method" unless base_url_value if name.is_a?(Hash) && == {} # If name is not set, use first parameter as the options hash = name name = self.class.to_s end super set_remove_keys(, %i[api_username default_hash template_name]) @init_options = @merged_options ||= # Caches initial merge options end |
Instance Attribute Details
#api_username ⇒ Object
User used in making API calls
27 28 29 |
# File 'lib/soaspec/exchange_handlers/rest_handler.rb', line 27 def api_username @api_username end |
Instance Method Details
#after_response(_response, _self) ⇒ Object
Override this with ‘after_response’ within class definition to perform an action after response is retrieved
52 |
# File 'lib/soaspec/exchange_handlers/rest_handler.rb', line 52 def after_response(_response, _self); end |
#calculated_json_path_matches(path, response, attribute, not_empty: false) ⇒ Array
Calculate all JSON path values based on rules. ‘,’, pascal_case
180 181 182 183 184 185 186 187 188 189 190 |
# File 'lib/soaspec/exchange_handlers/rest_handler.rb', line 180 def calculated_json_path_matches(path, response, attribute, not_empty: false) path = add_pascal_path(path) paths_to_check = path.split(',') paths_to_check = paths_to_check.map { |path_to_check| prefix_json_path(path_to_check) } matching_values = paths_to_check.collect do |path_to_check| json_path_values_for(response, path_to_check, attribute: attribute) end.reject(&:empty?) raise NoElementAtPath, "No value at JSONPath '#{paths_to_check}' in '#{response.body}'" if matching_values.empty? && not_empty matching_values.first end |
#found?(response) ⇒ Boolean
@@return [Boolean] Whether the request found the desired value or not
126 127 128 |
# File 'lib/soaspec/exchange_handlers/rest_handler.rb', line 126 def found?(response) status_code_for(response) != 404 end |
#hash_used_in_request(override_hash) ⇒ Hash
Returns Hash used in REST request based on data conversion.
75 76 77 78 79 80 81 82 |
# File 'lib/soaspec/exchange_handlers/rest_handler.rb', line 75 def hash_used_in_request(override_hash) request = override_hash ? @default_hash.merge(override_hash) : @default_hash if pascal_keys? request.map { |k, v| [convert_to_pascal_case(k.to_s), v] }.to_h else request end end |
#include_in_body?(response, expected) ⇒ Boolean
Returns Whether response body includes String.
121 122 123 |
# File 'lib/soaspec/exchange_handlers/rest_handler.rb', line 121 def include_in_body?(response, expected) response.body.include? expected end |
#include_key?(response, expected) ⇒ Boolean
Returns Whether response body contains expected key.
136 137 138 139 140 141 |
# File 'lib/soaspec/exchange_handlers/rest_handler.rb', line 136 def include_key?(response, expected) value_from_path(response, expected) true rescue NoElementAtPath false end |
#include_value?(response, expected) ⇒ Boolean
Returns Whether response contains expected value.
131 132 133 |
# File 'lib/soaspec/exchange_handlers/rest_handler.rb', line 131 def include_value?(response, expected) extract_hash(response).include_value? expected end |
#init_merge_options ⇒ Hash
Initialize value of merged options Also called to verify any issues with options on creating object
105 106 107 108 109 110 111 112 |
# File 'lib/soaspec/exchange_handlers/rest_handler.rb', line 105 def = .merge! basic_auth_params if respond_to? :basic_auth_params [:headers] ||= {} [:headers].merge! parse_headers [:headers][:authorization] ||= ERB.new('Bearer <%= access_token %>').result(binding) if Soaspec.auto_oauth && respond_to?(:access_token) .merge(@init_options) end |
#json_path_values_for(response, path, attribute: nil) ⇒ Enumerable
Returns List of values matching JSON path.
168 169 170 171 172 |
# File 'lib/soaspec/exchange_handlers/rest_handler.rb', line 168 def json_path_values_for(response, path, attribute: nil) raise 'JSON does not support attributes' if attribute JsonPath.on(response.body, path) end |
#make_request(override_parameters) ⇒ RestClient::Response
Used in together with Exchange request that passes such override parameters Following are for the body of the request
65 66 67 68 69 70 71 |
# File 'lib/soaspec/exchange_handlers/rest_handler.rb', line 65 def make_request(override_parameters) req_params = request_parameters override_parameters response = req_params.call @merged_options Soaspec::SpecLogger.info("response:\n headers: #{response&.headers}\n body: #{response}\n") after_response(response, self) response end |
#parse_headers ⇒ Hash
Perform ERB on each header value
94 95 96 97 98 99 100 |
# File 'lib/soaspec/exchange_handlers/rest_handler.rb', line 94 def parse_headers Hash[rest_client_headers.map do |header_name, header_value| raise ArgumentError, "Header '#{header_name}' is null. Headers are #{rest_client_headers}" if header_value.nil? [header_name, ERB.new(header_value).result(binding)] end] end |
#request(response) ⇒ RestClient::Request, String
Returns Request of API call. Either intended request or actual request.
233 234 235 236 237 238 239 240 |
# File 'lib/soaspec/exchange_handlers/rest_handler.rb', line 233 def request(response) if response.nil? return 'Request not yet sent. Call :request_parameters' \ 'for what will be sent' end response.request end |
#request_parameters(override_parameters) ⇒ Soaspec::RestRequest
Returns Parameters used in making a request.
45 46 47 |
# File 'lib/soaspec/exchange_handlers/rest_handler.rb', line 45 def request_parameters(override_parameters) RestRequest.new(override_parameters, @merged_options, self) end |
#response_body(response, format: :hash) ⇒ Object
Returns Generic body to be displayed in error messages.
116 117 118 |
# File 'lib/soaspec/exchange_handlers/rest_handler.rb', line 116 def response_body(response, format: :hash) extract_hash response end |
#rest_resource_options ⇒ Hash
Add values to here when extending this class to have default REST options. See rest client resource at github.com/rest-client/rest-client for details It’s easier to set headers via ‘headers’ accessor rather than here
88 89 90 |
# File 'lib/soaspec/exchange_handlers/rest_handler.rb', line 88 def {} end |
#status_code_for(response) ⇒ Integer
Returns HTTP Status code for response.
144 145 146 |
# File 'lib/soaspec/exchange_handlers/rest_handler.rb', line 144 def status_code_for(response) response&.code end |
#value_from_path(response, path, attribute: nil) ⇒ String
Based on a exchange, return the value at the provided xpath If the path does not begin with a ‘/’, a ‘//’ is added to it
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 |
# File 'lib/soaspec/exchange_handlers/rest_handler.rb', line 198 def value_from_path(response, path, attribute: nil) path = path.to_s case Interpreter.response_type_for(response) when :xml, :html result = xpath_elements_for(response: response, xpath: path, attribute: attribute).first raise NoElementAtPath, "No value at Xpath '#{prefix_xpath(path, attribute)}' in '#{response.body}'" unless result return result.inner_text if attribute.nil? return result.attributes[attribute].inner_text when :json matching_values = calculated_json_path_matches(path, response, attribute, not_empty: true) matching_values.first else # Assume this is a String raise NoElementAtPath, 'Response is empty' if response.to_s.empty? response.to_s[/#{path}/] # Perform regular expression using path if not XML nor JSON end end |
#values_from_path(response, path, attribute: nil) ⇒ Enumerable
Returns List of values returned from path.
218 219 220 221 222 223 224 225 226 227 228 229 230 |
# File 'lib/soaspec/exchange_handlers/rest_handler.rb', line 218 def values_from_path(response, path, attribute: nil) path = path.to_s case Interpreter.response_type_for(response) when :xml xpath_elements_for(response: response, xpath: path, attribute: attribute).map(&:inner_text) when :json result = calculated_json_path_matches(path, response, attribute) result || [] # json_path_values_for(response, path, attribute: attribute) else raise "Unable to interpret type of #{response.body}" end end |
#xpath_elements_for(response: nil, xpath: nil, attribute: nil) ⇒ Enumerable
Returns the value at the provided xpath
153 154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/soaspec/exchange_handlers/rest_handler.rb', line 153 def xpath_elements_for(response: nil, xpath: nil, attribute: nil) raise ArgumentError unless response && xpath raise "Can't perform XPATH if response is not XML" unless %i[xml html].include? Interpreter.response_type_for(response) xpath = prefix_xpath(xpath, attribute) temp_doc = Nokogiri.parse(response.body).dup if strip_namespaces? && !xpath.include?(':') temp_doc.remove_namespaces! temp_doc.xpath(xpath) else temp_doc.xpath(xpath, temp_doc.collect_namespaces) end end |