From 244a3b4c137fc7cb269f3ca07457d177551571fe Mon Sep 17 00:00:00 2001 From: Dawson Akins Conway Date: Sat, 28 Oct 2023 07:31:18 -0500 Subject: [PATCH] [ruby] Make File Downloads Threadsafe (#16876) * Make Generated Ruby Code Threadsafe * missed one * Generate Samples --- .../resources/ruby-client/api_client.mustache | 62 ---------------- .../api_client_faraday_partial.mustache | 40 +++++++++-- .../api_client_httpx_partial.mustache | 31 +++++++- .../api_client_typhoeus_partial.mustache | 16 +++-- .../lib/openapi_client/api_client.rb | 60 ++++++++-------- .../ruby-autoload/lib/petstore/api_client.rb | 21 +++--- .../ruby-faraday/lib/petstore/api_client.rb | 70 ++++++++++--------- .../ruby-httpx/lib/petstore/api_client.rb | 60 ++++++++-------- .../petstore/ruby/lib/petstore/api_client.rb | 21 +++--- .../lib/x_auth_id_alias/api_client.rb | 21 +++--- .../ruby/lib/dynamic_servers/api_client.rb | 21 +++--- .../ruby-client/lib/petstore/api_client.rb | 21 +++--- 12 files changed, 222 insertions(+), 222 deletions(-) diff --git a/modules/openapi-generator/src/main/resources/ruby-client/api_client.mustache b/modules/openapi-generator/src/main/resources/ruby-client/api_client.mustache index 230d46dc781..fef2e864c94 100644 --- a/modules/openapi-generator/src/main/resources/ruby-client/api_client.mustache +++ b/modules/openapi-generator/src/main/resources/ruby-client/api_client.mustache @@ -72,68 +72,6 @@ module {{moduleName}} # @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 - {{#isTyphoeus}} - return @tempfile if return_type == 'File' - {{/isTyphoeus}} - {{#isFaraday}} - if return_type == 'File' - if @config.return_binary_data == true - # return byte stream - encoding = body.encoding - return @stream.join.force_encoding(encoding) - else - # return file instead of binary data - 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 - end - {{/isFaraday}} - {{#isHttpx}} - if return_type == 'File' - if @config.return_binary_data == true - # TODO: force response encoding - return body.to_s - else - 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 = response.body.encoding - tempfile = Tempfile.open(prefix, @config.temp_folder_path, encoding: encoding) - response.copy_to(tempfile) - 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 - end - {{/isHttpx}} - return nil if body.nil? || body.empty? # return response body directly for String return type diff --git a/modules/openapi-generator/src/main/resources/ruby-client/api_client_faraday_partial.mustache b/modules/openapi-generator/src/main/resources/ruby-client/api_client_faraday_partial.mustache index cc7175e95f1..04d95d956a0 100644 --- a/modules/openapi-generator/src/main/resources/ruby-client/api_client_faraday_partial.mustache +++ b/modules/openapi-generator/src/main/resources/ruby-client/api_client_faraday_partial.mustache @@ -3,9 +3,11 @@ # @return [Array<(Object, Integer, Hash)>] an array of 3 elements: # the data deserialized from response body (could be nil), response status code and response headers. def call_api(http_method, path, opts = {}) + stream = nil begin response = connection(opts).public_send(http_method.to_sym.downcase) do |req| build_request(http_method, path, req, opts) + stream = download_file(request) if opts[:return_type] == 'File' || opts[:return_type] == 'Binary' end if config.debugging @@ -30,7 +32,9 @@ fail ApiError.new('Connection failed') end - if opts[:return_type] + if opts[:return_type] == 'File' || opts[:return_type] == 'Binary' + data = deserialize_file(stream) + elsif opts[:return_type] data = deserialize(response, opts[:return_type]) else data = nil @@ -72,7 +76,6 @@ request.url url request.params = query_params - download_file(request) if opts[:return_type] == 'File' || opts[:return_type] == 'Binary' request end @@ -109,11 +112,40 @@ end def download_file(request) - @stream = [] + stream = [] # handle streaming Responses request.options.on_data = Proc.new do |chunk, overall_received_bytes| - @stream << chunk + stream << chunk + end + stream + end + + def deserialize_file(response, stream) + body = response.body + if @config.return_binary_data == true + # return byte stream + encoding = body.encoding + stream.join.force_encoding(encoding) + else + # return file instead of binary data + 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`" + tempfile end end diff --git a/modules/openapi-generator/src/main/resources/ruby-client/api_client_httpx_partial.mustache b/modules/openapi-generator/src/main/resources/ruby-client/api_client_httpx_partial.mustache index 537593df118..7dd5221dacc 100644 --- a/modules/openapi-generator/src/main/resources/ruby-client/api_client_httpx_partial.mustache +++ b/modules/openapi-generator/src/main/resources/ruby-client/api_client_httpx_partial.mustache @@ -23,7 +23,9 @@ fail ApiError.new('Connection failed') end - if opts[:return_type] + if opts[:return_type] == 'File' + data = deserialize_file(response) + elsif opts[:return_type] data = deserialize(response, opts[:return_type]) else data = nil @@ -80,6 +82,33 @@ end end + def deserialize_file(response) + body = response.body + if @config.return_binary_data == true + # TODO: force response encoding + body.to_s + else + 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 = response.body.encoding + tempfile = Tempfile.open(prefix, @config.temp_folder_path, encoding: encoding) + response.copy_to(tempfile) + 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`" + + tempfile + end + end + def session return @session if defined?(@session) diff --git a/modules/openapi-generator/src/main/resources/ruby-client/api_client_typhoeus_partial.mustache b/modules/openapi-generator/src/main/resources/ruby-client/api_client_typhoeus_partial.mustache index 7b961b400d8..57872028dd8 100644 --- a/modules/openapi-generator/src/main/resources/ruby-client/api_client_typhoeus_partial.mustache +++ b/modules/openapi-generator/src/main/resources/ruby-client/api_client_typhoeus_partial.mustache @@ -1,9 +1,10 @@ # Call an API with given options. # # @return [Array<(Object, Integer, Hash)>] an array of 3 elements: - # the data deserialized from response body (could be nil), response status code and response headers. + # the data deserialized from response body (may be a Tempfile or nil), response status code and response headers. def call_api(http_method, path, opts = {}) request = build_request(http_method, path, opts) + tempfile = download_file(request) if opts[:return_type] == 'File' response = request.run if @config.debugging @@ -25,7 +26,9 @@ end end - if opts[:return_type] + if opts[:return_type] == 'File' + data = tempfile + elsif opts[:return_type] data = deserialize(response, opts[:return_type]) else data = nil @@ -83,9 +86,7 @@ end end - request = Typhoeus::Request.new(url, req_opts) - download_file(request) if opts[:return_type] == 'File' - request + Typhoeus::Request.new(url, req_opts) end # Builds the HTTP request body @@ -123,6 +124,8 @@ # process can use. # # @see Configuration#temp_folder_path + # + # @return [Tempfile] the tempfile generated def download_file(request) tempfile = nil encoding = nil @@ -137,7 +140,6 @@ prefix = prefix + '-' unless prefix.end_with?('-') encoding = response.body.encoding tempfile = Tempfile.open(prefix, @config.temp_folder_path, encoding: encoding) - @tempfile = tempfile end request.on_body do |chunk| chunk.force_encoding(encoding) @@ -152,4 +154,6 @@ "explicitly with `tempfile.delete`" end end + + tempfile end diff --git a/samples/client/echo_api/ruby-httpx/lib/openapi_client/api_client.rb b/samples/client/echo_api/ruby-httpx/lib/openapi_client/api_client.rb index e3e9c1e0f1d..25e7902fc96 100644 --- a/samples/client/echo_api/ruby-httpx/lib/openapi_client/api_client.rb +++ b/samples/client/echo_api/ruby-httpx/lib/openapi_client/api_client.rb @@ -69,7 +69,9 @@ module OpenapiClient fail ApiError.new('Connection failed') end - if opts[:return_type] + if opts[:return_type] == 'File' + data = deserialize_file(response) + elsif opts[:return_type] data = deserialize(response, opts[:return_type]) else data = nil @@ -126,6 +128,33 @@ module OpenapiClient end end + def deserialize_file(response) + body = response.body + if @config.return_binary_data == true + # TODO: force response encoding + body.to_s + else + 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 = response.body.encoding + tempfile = Tempfile.open(prefix, @config.temp_folder_path, encoding: encoding) + response.copy_to(tempfile) + 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`" + + tempfile + end + end + def session return @session if defined?(@session) @@ -168,35 +197,6 @@ module OpenapiClient # @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 - if return_type == 'File' - if @config.return_binary_data == true - # TODO: force response encoding - return body.to_s - else - 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 = response.body.encoding - tempfile = Tempfile.open(prefix, @config.temp_folder_path, encoding: encoding) - response.copy_to(tempfile) - 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 - end - return nil if body.nil? || body.empty? # return response body directly for String return type diff --git a/samples/client/petstore/ruby-autoload/lib/petstore/api_client.rb b/samples/client/petstore/ruby-autoload/lib/petstore/api_client.rb index f4a681dc6d2..ea242b65b27 100644 --- a/samples/client/petstore/ruby-autoload/lib/petstore/api_client.rb +++ b/samples/client/petstore/ruby-autoload/lib/petstore/api_client.rb @@ -46,9 +46,10 @@ module Petstore # Call an API with given options. # # @return [Array<(Object, Integer, Hash)>] an array of 3 elements: - # the data deserialized from response body (could be nil), response status code and response headers. + # the data deserialized from response body (may be a Tempfile or nil), response status code and response headers. def call_api(http_method, path, opts = {}) request = build_request(http_method, path, opts) + tempfile = download_file(request) if opts[:return_type] == 'File' response = request.run if @config.debugging @@ -70,7 +71,9 @@ module Petstore end end - if opts[:return_type] + if opts[:return_type] == 'File' + data = tempfile + elsif opts[:return_type] data = deserialize(response, opts[:return_type]) else data = nil @@ -126,9 +129,7 @@ module Petstore end end - request = Typhoeus::Request.new(url, req_opts) - download_file(request) if opts[:return_type] == 'File' - request + Typhoeus::Request.new(url, req_opts) end # Builds the HTTP request body @@ -166,6 +167,8 @@ module Petstore # process can use. # # @see Configuration#temp_folder_path + # + # @return [Tempfile] the tempfile generated def download_file(request) tempfile = nil encoding = nil @@ -180,7 +183,6 @@ module Petstore prefix = prefix + '-' unless prefix.end_with?('-') encoding = response.body.encoding tempfile = Tempfile.open(prefix, @config.temp_folder_path, encoding: encoding) - @tempfile = tempfile end request.on_body do |chunk| chunk.force_encoding(encoding) @@ -195,6 +197,8 @@ module Petstore "explicitly with `tempfile.delete`" end end + + tempfile end # Check if the given MIME is a JSON MIME. @@ -215,11 +219,6 @@ module Petstore # @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 - return @tempfile if return_type == 'File' - return nil if body.nil? || body.empty? # return response body directly for String return type diff --git a/samples/client/petstore/ruby-faraday/lib/petstore/api_client.rb b/samples/client/petstore/ruby-faraday/lib/petstore/api_client.rb index cb459fa9056..63331a6ca3d 100644 --- a/samples/client/petstore/ruby-faraday/lib/petstore/api_client.rb +++ b/samples/client/petstore/ruby-faraday/lib/petstore/api_client.rb @@ -49,9 +49,11 @@ module Petstore # @return [Array<(Object, Integer, Hash)>] an array of 3 elements: # the data deserialized from response body (could be nil), response status code and response headers. def call_api(http_method, path, opts = {}) + stream = nil begin response = connection(opts).public_send(http_method.to_sym.downcase) do |req| build_request(http_method, path, req, opts) + stream = download_file(request) if opts[:return_type] == 'File' || opts[:return_type] == 'Binary' end if config.debugging @@ -76,7 +78,9 @@ module Petstore fail ApiError.new('Connection failed') end - if opts[:return_type] + if opts[:return_type] == 'File' || opts[:return_type] == 'Binary' + data = deserialize_file(stream) + elsif opts[:return_type] data = deserialize(response, opts[:return_type]) else data = nil @@ -118,7 +122,6 @@ module Petstore request.url url request.params = query_params - download_file(request) if opts[:return_type] == 'File' || opts[:return_type] == 'Binary' request end @@ -155,11 +158,40 @@ module Petstore end def download_file(request) - @stream = [] + stream = [] # handle streaming Responses request.options.on_data = Proc.new do |chunk, overall_received_bytes| - @stream << chunk + stream << chunk + end + stream + end + + def deserialize_file(response, stream) + body = response.body + if @config.return_binary_data == true + # return byte stream + encoding = body.encoding + stream.join.force_encoding(encoding) + else + # return file instead of binary data + 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`" + tempfile end end @@ -226,36 +258,6 @@ module Petstore # @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 - if return_type == 'File' - if @config.return_binary_data == true - # return byte stream - encoding = body.encoding - return @stream.join.force_encoding(encoding) - else - # return file instead of binary data - 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 - end - return nil if body.nil? || body.empty? # return response body directly for String return type diff --git a/samples/client/petstore/ruby-httpx/lib/petstore/api_client.rb b/samples/client/petstore/ruby-httpx/lib/petstore/api_client.rb index fe5e25ab387..899e01d632a 100644 --- a/samples/client/petstore/ruby-httpx/lib/petstore/api_client.rb +++ b/samples/client/petstore/ruby-httpx/lib/petstore/api_client.rb @@ -69,7 +69,9 @@ module Petstore fail ApiError.new('Connection failed') end - if opts[:return_type] + if opts[:return_type] == 'File' + data = deserialize_file(response) + elsif opts[:return_type] data = deserialize(response, opts[:return_type]) else data = nil @@ -126,6 +128,33 @@ module Petstore end end + def deserialize_file(response) + body = response.body + if @config.return_binary_data == true + # TODO: force response encoding + body.to_s + else + 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 = response.body.encoding + tempfile = Tempfile.open(prefix, @config.temp_folder_path, encoding: encoding) + response.copy_to(tempfile) + 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`" + + tempfile + end + end + def session return @session if defined?(@session) @@ -168,35 +197,6 @@ module Petstore # @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 - if return_type == 'File' - if @config.return_binary_data == true - # TODO: force response encoding - return body.to_s - else - 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 = response.body.encoding - tempfile = Tempfile.open(prefix, @config.temp_folder_path, encoding: encoding) - response.copy_to(tempfile) - 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 - end - return nil if body.nil? || body.empty? # return response body directly for String return type diff --git a/samples/client/petstore/ruby/lib/petstore/api_client.rb b/samples/client/petstore/ruby/lib/petstore/api_client.rb index f4a681dc6d2..ea242b65b27 100644 --- a/samples/client/petstore/ruby/lib/petstore/api_client.rb +++ b/samples/client/petstore/ruby/lib/petstore/api_client.rb @@ -46,9 +46,10 @@ module Petstore # Call an API with given options. # # @return [Array<(Object, Integer, Hash)>] an array of 3 elements: - # the data deserialized from response body (could be nil), response status code and response headers. + # the data deserialized from response body (may be a Tempfile or nil), response status code and response headers. def call_api(http_method, path, opts = {}) request = build_request(http_method, path, opts) + tempfile = download_file(request) if opts[:return_type] == 'File' response = request.run if @config.debugging @@ -70,7 +71,9 @@ module Petstore end end - if opts[:return_type] + if opts[:return_type] == 'File' + data = tempfile + elsif opts[:return_type] data = deserialize(response, opts[:return_type]) else data = nil @@ -126,9 +129,7 @@ module Petstore end end - request = Typhoeus::Request.new(url, req_opts) - download_file(request) if opts[:return_type] == 'File' - request + Typhoeus::Request.new(url, req_opts) end # Builds the HTTP request body @@ -166,6 +167,8 @@ module Petstore # process can use. # # @see Configuration#temp_folder_path + # + # @return [Tempfile] the tempfile generated def download_file(request) tempfile = nil encoding = nil @@ -180,7 +183,6 @@ module Petstore prefix = prefix + '-' unless prefix.end_with?('-') encoding = response.body.encoding tempfile = Tempfile.open(prefix, @config.temp_folder_path, encoding: encoding) - @tempfile = tempfile end request.on_body do |chunk| chunk.force_encoding(encoding) @@ -195,6 +197,8 @@ module Petstore "explicitly with `tempfile.delete`" end end + + tempfile end # Check if the given MIME is a JSON MIME. @@ -215,11 +219,6 @@ module Petstore # @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 - return @tempfile if return_type == 'File' - return nil if body.nil? || body.empty? # return response body directly for String return type diff --git a/samples/openapi3/client/extensions/x-auth-id-alias/ruby-client/lib/x_auth_id_alias/api_client.rb b/samples/openapi3/client/extensions/x-auth-id-alias/ruby-client/lib/x_auth_id_alias/api_client.rb index b9165625587..96123f70895 100644 --- a/samples/openapi3/client/extensions/x-auth-id-alias/ruby-client/lib/x_auth_id_alias/api_client.rb +++ b/samples/openapi3/client/extensions/x-auth-id-alias/ruby-client/lib/x_auth_id_alias/api_client.rb @@ -46,9 +46,10 @@ module XAuthIDAlias # Call an API with given options. # # @return [Array<(Object, Integer, Hash)>] an array of 3 elements: - # the data deserialized from response body (could be nil), response status code and response headers. + # the data deserialized from response body (may be a Tempfile or nil), response status code and response headers. def call_api(http_method, path, opts = {}) request = build_request(http_method, path, opts) + tempfile = download_file(request) if opts[:return_type] == 'File' response = request.run if @config.debugging @@ -70,7 +71,9 @@ module XAuthIDAlias end end - if opts[:return_type] + if opts[:return_type] == 'File' + data = tempfile + elsif opts[:return_type] data = deserialize(response, opts[:return_type]) else data = nil @@ -126,9 +129,7 @@ module XAuthIDAlias end end - request = Typhoeus::Request.new(url, req_opts) - download_file(request) if opts[:return_type] == 'File' - request + Typhoeus::Request.new(url, req_opts) end # Builds the HTTP request body @@ -166,6 +167,8 @@ module XAuthIDAlias # process can use. # # @see Configuration#temp_folder_path + # + # @return [Tempfile] the tempfile generated def download_file(request) tempfile = nil encoding = nil @@ -180,7 +183,6 @@ module XAuthIDAlias prefix = prefix + '-' unless prefix.end_with?('-') encoding = response.body.encoding tempfile = Tempfile.open(prefix, @config.temp_folder_path, encoding: encoding) - @tempfile = tempfile end request.on_body do |chunk| chunk.force_encoding(encoding) @@ -195,6 +197,8 @@ module XAuthIDAlias "explicitly with `tempfile.delete`" end end + + tempfile end # Check if the given MIME is a JSON MIME. @@ -215,11 +219,6 @@ module XAuthIDAlias # @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 - return @tempfile if return_type == 'File' - return nil if body.nil? || body.empty? # return response body directly for String return type diff --git a/samples/openapi3/client/features/dynamic-servers/ruby/lib/dynamic_servers/api_client.rb b/samples/openapi3/client/features/dynamic-servers/ruby/lib/dynamic_servers/api_client.rb index 378180347db..5429313bd7f 100644 --- a/samples/openapi3/client/features/dynamic-servers/ruby/lib/dynamic_servers/api_client.rb +++ b/samples/openapi3/client/features/dynamic-servers/ruby/lib/dynamic_servers/api_client.rb @@ -46,9 +46,10 @@ module DynamicServers # Call an API with given options. # # @return [Array<(Object, Integer, Hash)>] an array of 3 elements: - # the data deserialized from response body (could be nil), response status code and response headers. + # the data deserialized from response body (may be a Tempfile or nil), response status code and response headers. def call_api(http_method, path, opts = {}) request = build_request(http_method, path, opts) + tempfile = download_file(request) if opts[:return_type] == 'File' response = request.run if @config.debugging @@ -70,7 +71,9 @@ module DynamicServers end end - if opts[:return_type] + if opts[:return_type] == 'File' + data = tempfile + elsif opts[:return_type] data = deserialize(response, opts[:return_type]) else data = nil @@ -125,9 +128,7 @@ module DynamicServers end end - request = Typhoeus::Request.new(url, req_opts) - download_file(request) if opts[:return_type] == 'File' - request + Typhoeus::Request.new(url, req_opts) end # Builds the HTTP request body @@ -165,6 +166,8 @@ module DynamicServers # process can use. # # @see Configuration#temp_folder_path + # + # @return [Tempfile] the tempfile generated def download_file(request) tempfile = nil encoding = nil @@ -179,7 +182,6 @@ module DynamicServers prefix = prefix + '-' unless prefix.end_with?('-') encoding = response.body.encoding tempfile = Tempfile.open(prefix, @config.temp_folder_path, encoding: encoding) - @tempfile = tempfile end request.on_body do |chunk| chunk.force_encoding(encoding) @@ -194,6 +196,8 @@ module DynamicServers "explicitly with `tempfile.delete`" end end + + tempfile end # Check if the given MIME is a JSON MIME. @@ -214,11 +218,6 @@ module DynamicServers # @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 - return @tempfile if return_type == 'File' - return nil if body.nil? || body.empty? # return response body directly for String return type diff --git a/samples/openapi3/client/features/generate-alias-as-model/ruby-client/lib/petstore/api_client.rb b/samples/openapi3/client/features/generate-alias-as-model/ruby-client/lib/petstore/api_client.rb index cf94fdc965a..0132e630b04 100644 --- a/samples/openapi3/client/features/generate-alias-as-model/ruby-client/lib/petstore/api_client.rb +++ b/samples/openapi3/client/features/generate-alias-as-model/ruby-client/lib/petstore/api_client.rb @@ -46,9 +46,10 @@ module Petstore # Call an API with given options. # # @return [Array<(Object, Integer, Hash)>] an array of 3 elements: - # the data deserialized from response body (could be nil), response status code and response headers. + # the data deserialized from response body (may be a Tempfile or nil), response status code and response headers. def call_api(http_method, path, opts = {}) request = build_request(http_method, path, opts) + tempfile = download_file(request) if opts[:return_type] == 'File' response = request.run if @config.debugging @@ -70,7 +71,9 @@ module Petstore end end - if opts[:return_type] + if opts[:return_type] == 'File' + data = tempfile + elsif opts[:return_type] data = deserialize(response, opts[:return_type]) else data = nil @@ -125,9 +128,7 @@ module Petstore end end - request = Typhoeus::Request.new(url, req_opts) - download_file(request) if opts[:return_type] == 'File' - request + Typhoeus::Request.new(url, req_opts) end # Builds the HTTP request body @@ -165,6 +166,8 @@ module Petstore # process can use. # # @see Configuration#temp_folder_path + # + # @return [Tempfile] the tempfile generated def download_file(request) tempfile = nil encoding = nil @@ -179,7 +182,6 @@ module Petstore prefix = prefix + '-' unless prefix.end_with?('-') encoding = response.body.encoding tempfile = Tempfile.open(prefix, @config.temp_folder_path, encoding: encoding) - @tempfile = tempfile end request.on_body do |chunk| chunk.force_encoding(encoding) @@ -194,6 +196,8 @@ module Petstore "explicitly with `tempfile.delete`" end end + + tempfile end # Check if the given MIME is a JSON MIME. @@ -214,11 +218,6 @@ module Petstore # @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 - return @tempfile if return_type == 'File' - return nil if body.nil? || body.empty? # return response body directly for String return type