=begin {{> api_info}} =end require 'date' require 'json' require 'logger' require 'tempfile' require 'time' {{^isFaraday}} require 'typhoeus' {{/isFaraday}} {{#isFaraday}} require 'faraday' {{/isFaraday}} module {{moduleName}} class APIClient # The Configuration object holding settings to be used in the API client. attr_accessor :config # Defines the headers to be used in HTTP requests of all API calls by default. # # @return [Hash] attr_accessor :default_headers # Initializes the APIClient # @option config [Configuration] Configuration for initializing the object, default to Configuration.default def initialize(config = Configuration.default) @config = config @user_agent = "{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/#{VERSION}/ruby{{/httpUserAgent}}" @default_headers = { 'Content-Type' => 'application/json', 'User-Agent' => @user_agent } end def self.default @@default ||= APIClient.new end {{^isFaraday}} {{> api_client_typhoeus_partial}} {{/isFaraday}} {{#isFaraday}} {{> api_client_faraday_partial}} {{/isFaraday}} # Check if the given MIME is a JSON MIME. # JSON MIME examples: # application/json # application/json; charset=UTF8 # APPLICATION/JSON # */* # @param [String] mime MIME # @return [Boolean] True if the MIME is application/json def json_mime?(mime) (mime == '*/*') || !(mime =~ /Application\/.*json(?!p)(;.*)?/i).nil? || (mime == 'text/json') end # Deserialize the response to the given return type. # # @param [Response] response HTTP response # @param [String] return_type some examples: "User", "Array", "Hash" def deserialize(response, return_type) body = response.body # handle file downloading - return the File instance processed in request callbacks # note that response body is empty when the file is written in chunks in request on_body callback {{^isFaraday}} return @tempfile if return_type == 'File' {{/isFaraday}} {{#isFaraday}} if return_type == 'File' content_disposition = response.headers['Content-Disposition'] if content_disposition && content_disposition =~ /filename=/i filename = content_disposition[/filename=['"]?([^'"\s]+)['"]?/, 1] prefix = sanitize_filename(filename) else prefix = 'download-' end prefix = prefix + '-' unless prefix.end_with?('-') encoding = body.encoding @tempfile = Tempfile.open(prefix, @config.temp_folder_path, encoding: encoding) @tempfile.write(@stream.join.force_encoding(encoding)) @tempfile.close @config.logger.info "Temp file written to #{@tempfile.path}, please copy the file to a proper folder "\ "with e.g. `FileUtils.cp(tempfile.path, '/new/file/path')` otherwise the temp file "\ "will be deleted automatically with GC. It's also recommended to delete the temp file "\ "explicitly with `tempfile.delete`" return @tempfile end {{/isFaraday}} return nil if body.nil? || body.empty? # return response body directly for String return type return body if return_type == 'String' # ensuring a default content type content_type = response.headers['Content-Type'] || 'application/json' fail "Content-Type is not supported: #{content_type}" unless json_mime?(content_type) begin data = JSON.parse("[#{body}]", :symbolize_names => true)[0] rescue JSON::ParserError => e if %w(String Date Time).include?(return_type) data = body else raise e end end convert_to_type data, return_type end # Convert data to the given return type. # @param [Object] data Data to be converted # @param [String] return_type Return type # @return [Mixed] Data in a particular type def convert_to_type(data, return_type) return nil if data.nil? case return_type when 'String' data.to_s when 'Integer' data.to_i when 'Float' data.to_f when 'Boolean' data == true when 'Time' # parse date time (expecting ISO 8601 format) Time.parse data when 'Date' # parse date time (expecting ISO 8601 format) Date.parse data when 'Object' # generic object (usually a Hash), return directly data when /\AArray<(.+)>\z/ # e.g. Array sub_type = $1 data.map { |item| convert_to_type(item, sub_type) } when /\AHash\\z/ # e.g. Hash sub_type = $1 {}.tap do |hash| data.each { |k, v| hash[k] = convert_to_type(v, sub_type) } end else # models (e.g. Pet) or oneOf klass = {{moduleName}}.const_get(return_type) klass.respond_to?(:openapi_one_of) ? klass.build(data) : klass.build_from_hash(data) end end # Sanitize filename by removing path. # e.g. ../../sun.gif becomes sun.gif # # @param [String] filename the filename to be sanitized # @return [String] the sanitized filename def sanitize_filename(filename) filename.gsub(/.*[\/\\]/, '') end def build_request_url(path, opts = {}) # Add leading and trailing slashes to path path = "/#{path}".gsub(/\/+/, '/') @config.base_url(opts[:operation]) + path end # Update hearder and query params based on authentication settings. # # @param [Hash] header_params Header parameters # @param [Hash] query_params Query parameters # @param [String] auth_names Authentication scheme name def update_params_for_auth!(header_params, query_params, auth_names) Array(auth_names).each do |auth_name| auth_setting = @config.auth_settings[auth_name] next unless auth_setting case auth_setting[:in] when 'header' then header_params[auth_setting[:key]] = auth_setting[:value] when 'query' then query_params[auth_setting[:key]] = auth_setting[:value] else fail ArgumentError, 'Authentication token must be in `query` or `header`' end end end # Sets user agent in HTTP header # # @param [String] user_agent User agent (e.g. openapi-generator/ruby/1.0.0) def user_agent=(user_agent) @user_agent = user_agent @default_headers['User-Agent'] = @user_agent end # Return Accept header based on an array of accepts provided. # @param [Array] accepts array for Accept # @return [String] the Accept header (e.g. application/json) def select_header_accept(accepts) return nil if accepts.nil? || accepts.empty? # use JSON when present, otherwise use all of the provided json_accept = accepts.find { |s| json_mime?(s) } json_accept || accepts.join(',') end # Return Content-Type header based on an array of content types provided. # @param [Array] content_types array for Content-Type # @return [String] the Content-Type header (e.g. application/json) def select_header_content_type(content_types) # use application/json by default return 'application/json' if content_types.nil? || content_types.empty? # use JSON when present, otherwise use the first one json_content_type = content_types.find { |s| json_mime?(s) } json_content_type || content_types.first end # Convert object (array, hash, object, etc) to JSON string. # @param [Object] model object to be converted into JSON string # @return [String] JSON string representation of the object def object_to_http_body(model) return model if model.nil? || model.is_a?(String) local_body = nil if model.is_a?(Array) local_body = model.map { |m| object_to_hash(m) } else local_body = object_to_hash(model) end local_body.to_json end # Convert object(non-array) to hash. # @param [Object] obj object to be converted into JSON string # @return [String] JSON string representation of the object def object_to_hash(obj) if obj.respond_to?(:to_hash) obj.to_hash else obj end end # Build parameter value according to the given collection format. # @param [String] collection_format one of :csv, :ssv, :tsv, :pipes and :multi def build_collection_param(param, collection_format) case collection_format when :csv param.join(',') when :ssv param.join(' ') when :tsv param.join("\t") when :pipes param.join('|') when :multi # return the array directly as typhoeus will handle it as expected param else fail "unknown collection format: #{collection_format.inspect}" end end end end