Class: Scorpio::Request
- Inherits:
-
Object
- Object
- Scorpio::Request
- Includes:
- Configurables
- Defined in:
- lib/scorpio/request.rb
Defined Under Namespace
Modules: Configurables
Constant Summary collapse
- SUPPORTED_REQUEST_MEDIA_TYPES =
media types for which Scorpio has implemented generating / parsing between body and body_object (see Configurables#body and Scorpio::Response#body_object)
%w( application/json application/x-www-form-urlencoded ).map(&:freeze).freeze
- FALLBACK_CONTENT_TYPE =
'application/x-www-form-urlencoded'.freeze
- METHODS_WITH_BODIES =
see also Faraday::Env::MethodsWithBodies
%w(post put patch options).map(&:freeze).freeze
Instance Attribute Summary collapse
Attributes included from Configurables
#base_url, #body, #body_object, #faraday_adapter, #faraday_builder, #headers, #logger, #media_type, #path_params, #query_params, #scheme, #server, #server_variables, #user_agent
Class Method Summary collapse
- .best_media_type(media_types) ⇒ Object
- .method_with_body?(http_method) ⇒ Boolean
- .request_class_by_operation(operation) ⇒ Object
Instance Method Summary collapse
-
#content_type ⇒ ::Ur::ContentType
Content-Type for this request, taken from request headers if present, or the request Configurables#media_type.
-
#content_type_header ⇒ ::Ur::ContentType
the value of the request Content-Type header.
-
#each_page_ur(next_page:, raise_on_http_error: true) {|Scorpio::Ur| ... } ⇒ Enumerator?
Runs this request, passing the resulting Ur to the given block.
-
#faraday_connection(yield_ur = nil) ⇒ ::Faraday::Connection
builds a Faraday connection with this Request's faraday_builder and faraday_adapter.
-
#get_param(name) ⇒ Object
returns the value of the named parameter on this request.
-
#get_param_from(param_in, name) ⇒ Object
returns the value of the named parameter from the specified
param_in
on this request. -
#http_method ⇒ String
the http method for this request.
-
#initialize(configuration = {}, &b) ⇒ Request
constructor
A new instance of Request.
- #openapi_document ⇒ Scorpio::OpenAPI::Document
- #param_for(name) ⇒ #to_hash?
- #param_for!(name) ⇒ #to_hash
-
#path ⇒ Addressable::URI
an Addressable::URI containing only the path to append to the Configurables#base_url for this request.
-
#path_template ⇒ Addressable::Template
the template for the request's path, to be expanded with Configurables#path_params and appended to the request's Configurables#base_url.
- #request_schema(media_type: self.media_type) ⇒ ::JSI::Schema
-
#run ⇒ Object
runs this request.
-
#run_ur ⇒ Scorpio::Ur
runs this request and returns the full representation of the request that was run and its response.
-
#set_param(name, value) ⇒ Object
if there is only one parameter with the given name, of any sort, this will set it.
-
#set_param_from(param_in, name, value) ⇒ Object
applies the named value to the appropriate parameter of the request.
-
#url ⇒ Addressable::URI
the full URL for this request.
Constructor Details
#initialize(configuration = {}, &b) ⇒ Request
Returns a new instance of Request.
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/scorpio/request.rb', line 146 def initialize(configuration = {}, &b) configuration = JSI::Util.stringify_symbol_keys(configuration) params_set = Set.new # the set of params that have been set # do the Configurables first configuration.each do |name, value| if Configurables.public_method_defined?("#{name}=") Configurables.instance_method("#{name}=").bind(self).call(value) params_set << name end end # then do other top-level params configuration.reject { |name, _| params_set.include?(name) }.each do |name, value| param = param_for(name) || raise(ArgumentError, "unrecognized configuration value passed: #{name.inspect}") set_param_from(param['in'], param['name'], value) end if block_given? yield self end end |
Instance Attribute Details
#operation ⇒ Scorpio::OpenAPI::Operation (readonly)
168 169 170 |
# File 'lib/scorpio/request.rb', line 168 def operation @operation end |
Class Method Details
.best_media_type(media_types) ⇒ Object
17 18 19 20 21 22 23 |
# File 'lib/scorpio/request.rb', line 17 def self.best_media_type(media_types) if media_types.size == 1 media_types.first else SUPPORTED_REQUEST_MEDIA_TYPES.detect { |mt| media_types.include?(mt) } end end |
.method_with_body?(http_method) ⇒ Boolean
27 28 29 30 |
# File 'lib/scorpio/request.rb', line 27 def self.method_with_body?(http_method) raise(ArgumentError) unless http_method.is_a?(String) METHODS_WITH_BODIES.include?(http_method.downcase) end |
.request_class_by_operation(operation) ⇒ Object
139 140 141 |
# File 'lib/scorpio/request.rb', line 139 def self.request_class_by_operation(operation) @request_class_by_operation[operation] end |
Instance Method Details
#content_type ⇒ ::Ur::ContentType
Content-Type for this request, taken from request headers if present, or the request Scorpio::Request::Configurables#media_type.
233 234 235 |
# File 'lib/scorpio/request.rb', line 233 def content_type content_type_header || (media_type ? ::Ur::ContentType.new(media_type) : nil) end |
#content_type_header ⇒ ::Ur::ContentType
the value of the request Content-Type header
223 224 225 226 227 228 |
# File 'lib/scorpio/request.rb', line 223 def content_type_header headers.each do |k, v| return ::Ur::ContentType.new(v) if k =~ /\Acontent[-_]type\z/i end nil end |
#each_page_ur(next_page:, raise_on_http_error: true) {|Scorpio::Ur| ... } ⇒ Enumerator?
Runs this request, passing the resulting Ur to the given block.
The next_page
callable is then called with that Ur and results in the next page's Ur, or nil.
This repeats until the next_page
call results in nil.
See OpenAPI::Operation#each_link_page for integration with an OpenAPI Operation.
404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 |
# File 'lib/scorpio/request.rb', line 404 def each_page_ur(next_page: , raise_on_http_error: true) return to_enum(__method__, next_page: next_page, raise_on_http_error: raise_on_http_error) unless block_given? page_ur = run_ur while page_ur unless page_ur.is_a?(Scorpio::Ur) raise(TypeError, [ "next_page must result in a #{Scorpio::Ur}", "this should be the result of #run_ur from a #{OpenAPI::Operation} or #{Request}", ].join("\n")) end page_ur.raise_on_http_error if raise_on_http_error yield page_ur page_ur = next_page.call(page_ur) end nil end |
#faraday_connection(yield_ur = nil) ⇒ ::Faraday::Connection
builds a Faraday connection with this Request's faraday_builder and faraday_adapter. passes a given proc yield_ur to middleware to yield an Ur for requests made with the connection.
247 248 249 250 251 252 253 254 255 256 257 |
# File 'lib/scorpio/request.rb', line 247 def faraday_connection(yield_ur = nil) Faraday.new do |faraday_connection| faraday_builder.call(faraday_connection) if yield_ur -> { ::Ur::Faraday }.() # autoload trigger faraday_connection.response(:yield_ur, schemas: Set[Scorpio::Ur.schema], logger: self.logger, &yield_ur) end faraday_connection.adapter(*faraday_adapter) end end |
#get_param(name) ⇒ Object
returns the value of the named parameter on this request
275 276 277 278 |
# File 'lib/scorpio/request.rb', line 275 def get_param(name) param = param_for!(name) get_param_from(param['in'], param['name']) end |
#get_param_from(param_in, name) ⇒ Object
returns the value of the named parameter from the specified param_in
on this request
337 338 339 340 341 342 343 344 345 346 347 348 349 350 |
# File 'lib/scorpio/request.rb', line 337 def get_param_from(param_in, name) if param_in == 'path' path_params[name] elsif param_in == 'query' query_params ? query_params[name] : nil elsif param_in == 'header' _, value = headers.detect { |headername, _| headername.downcase == name.downcase } value elsif param_in == 'cookie' raise(NotImplementedError, "cookies not implemented: #{name.inspect}") else raise(OpenAPI::SemanticError, "cannot get param from param_in = #{param_in.inspect} (name: #{name.pretty_inspect.chomp})") end end |
#http_method ⇒ String
the http method for this request
177 178 179 |
# File 'lib/scorpio/request.rb', line 177 def http_method operation.http_method end |
#openapi_document ⇒ Scorpio::OpenAPI::Document
171 172 173 |
# File 'lib/scorpio/request.rb', line 171 def openapi_document operation.openapi_document end |
#param_for(name) ⇒ #to_hash?
283 284 285 286 287 288 289 290 291 292 293 294 295 |
# File 'lib/scorpio/request.rb', line 283 def param_for(name) name = name.to_s if name.is_a?(Symbol) params = operation.inferred_parameters.select { |p| p['name'] == name } if params.size == 1 params.first elsif params.size == 0 nil else raise(AmbiguousParameter.new( "There are multiple parameters for #{name}. matched parameters were: #{params.pretty_inspect.chomp}" ).tap { |e| e.name = name }) end end |
#param_for!(name) ⇒ #to_hash
301 302 303 |
# File 'lib/scorpio/request.rb', line 301 def param_for!(name) param_for(name) || raise(ParameterError, "There is no parameter named #{name} on operation #{operation.human_id}:\n#{operation.pretty_inspect.chomp}") end |
#path ⇒ Addressable::URI
an Addressable::URI containing only the path to append to the Scorpio::Request::Configurables#base_url for this request
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 |
# File 'lib/scorpio/request.rb', line 190 def path path_params = JSI::Util.stringify_symbol_keys(self.path_params) missing_variables = path_template.variables - path_params.keys if missing_variables.any? raise(ArgumentError, "path #{operation.path_template_str} for operation #{operation.human_id} requires path_params " + "which were missing: #{missing_variables.inspect}") end empty_variables = path_template.variables.select { |v| path_params[v].to_s.empty? } if empty_variables.any? raise(ArgumentError, "path #{operation.path_template_str} for operation #{operation.human_id} requires path_params " + "which were empty: #{empty_variables.inspect}") end path = path_template.(path_params) if query_params path.query_values = query_params end path.freeze end |
#path_template ⇒ Addressable::Template
the template for the request's path, to be expanded with Scorpio::Request::Configurables#path_params and appended to the request's Scorpio::Request::Configurables#base_url
184 185 186 |
# File 'lib/scorpio/request.rb', line 184 def path_template operation.path_template end |
#request_schema(media_type: self.media_type) ⇒ ::JSI::Schema
238 239 240 |
# File 'lib/scorpio/request.rb', line 238 def request_schema(media_type: self.media_type) operation.request_schema(media_type: media_type) end |
#run ⇒ Object
runs this request. returns the response body object - that is, the response body parsed according to an understood media type, and instantiated with the applicable response schema if one is specified. see Scorpio::Response#body_object for more detail.
387 388 389 390 391 |
# File 'lib/scorpio/request.rb', line 387 def run ur = run_ur ur.raise_on_http_error ur.response.body_object end |
#run_ur ⇒ Scorpio::Ur
runs this request and returns the full representation of the request that was run and its response.
355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 |
# File 'lib/scorpio/request.rb', line 355 def run_ur headers = {} if user_agent headers['User-Agent'] = user_agent end if !content_type_header if media_type headers['Content-Type'] = media_type else # I'd rather not have a default content-type, but if none is set then the HTTP adapter sets this to # application/x-www-form-urlencoded and issues a warning about it. if METHODS_WITH_BODIES.include?(http_method.to_s) headers['Content-Type'] = FALLBACK_CONTENT_TYPE end end end headers.update(self.headers) body = self.body ur = nil conn = faraday_connection(-> (yur) { ur = yur }) conn.run_request(http_method.downcase.to_sym, url, body, headers) ur.scorpio_request = self ur end |
#set_param(name, value) ⇒ Object
if there is only one parameter with the given name, of any sort, this will set it.
265 266 267 268 269 |
# File 'lib/scorpio/request.rb', line 265 def set_param(name, value) param = param_for!(name) set_param_from(param['in'], param['name'], value) value end |
#set_param_from(param_in, name, value) ⇒ Object
applies the named value to the appropriate parameter of the request
313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 |
# File 'lib/scorpio/request.rb', line 313 def set_param_from(param_in, name, value) param_in = param_in.to_s if param_in.is_a?(Symbol) name = name.to_s if name.is_a?(Symbol) if param_in == 'path' self.path_params = self.path_params.merge(name => value) elsif param_in == 'query' self.query_params = (self.query_params || {}).merge(name => value) elsif param_in == 'header' self.headers = self.headers.merge(name => value) elsif param_in == 'cookie' raise(NotImplementedError, "cookies not implemented: #{name.inspect} => #{value.inspect}") else raise(ArgumentError, "cannot set param from param_in = #{param_in.inspect} (name: #{name.pretty_inspect.chomp}, value: #{value.pretty_inspect.chomp})") end value end |
#url ⇒ Addressable::URI
the full URL for this request
212 213 214 215 216 217 218 219 |
# File 'lib/scorpio/request.rb', line 212 def url unless base_url raise(ArgumentError, "no base_url has been specified for request") end # we do not use Addressable::URI#join as the paths should just be concatenated, not resolved. # we use File.join just to deal with consecutive slashes. Addressable::URI.parse(File.join(base_url, path)).freeze end |