From f90012cf36624f80b942a7b998455d1fe46dfdc1 Mon Sep 17 00:00:00 2001 From: shinji Date: Fri, 14 Aug 2020 16:31:30 +0900 Subject: [PATCH] [TRN-927] handle 302 redirect --- Gemfile | 3 +++ lib/gengo-ruby/api_handler.rb | 49 +++++++++++++++++++++++------------ spec/api_redirect_spec.rb | 40 ++++++++++++++++++++++++++++ spec/spec_helper.rb | 3 +++ 4 files changed, 78 insertions(+), 17 deletions(-) create mode 100644 spec/api_redirect_spec.rb diff --git a/Gemfile b/Gemfile index 259e599..71496d6 100644 --- a/Gemfile +++ b/Gemfile @@ -2,3 +2,6 @@ source "http://rubygems.org" # Specify your gem's dependencies in gengo-ruby.gemspec gemspec + +# Added at 2020-08-14 15:41:23 +0900 by kohara-shinji: +gem "webmock", "~> 3.8" diff --git a/lib/gengo-ruby/api_handler.rb b/lib/gengo-ruby/api_handler.rb index bc0d608..106a8cd 100644 --- a/lib/gengo-ruby/api_handler.rb +++ b/lib/gengo-ruby/api_handler.rb @@ -107,24 +107,11 @@ def get_from_gengo(endpoint, params = {}) headers.merge!('Authorization' => access_token_bearer) end - endpoint << "?api_sig=" + signature_of(query[:ts]) - endpoint << '&' + query.map { |k, v| "#{k}=#{urlencode(v)}" }.join('&') + options = "?api_sig=" + signature_of(query[:ts]) + options << '&' + query.map { |k, v| "#{k}=#{urlencode(v)}" }.join('&') - uri = "/v#{@opts[:api_version]}/" + endpoint - - if is_delete - req = Net::HTTP::Delete.new(uri, headers) - else - req = Net::HTTP::Get.new(uri, headers) - end - - url = URI.parse("https://#{@api_host}") - http = Net::HTTP.start(url.host, url.port, use_ssl: true) - if @debug - http.set_debug_output($stdout) - end - http.read_timeout = 5*60 - resp = http.request(req) + url_str = "https://#{@api_host}/v#{@opts[:api_version]}/" + endpoint + resp = call_api(url_str, headers, is_delete, options) return resp.body if is_download_file @@ -145,6 +132,34 @@ def get_from_gengo(endpoint, params = {}) return json end + def call_api(url_str, headers, is_delete, options, limit = 10) + raise ArgumentError, 'HTTP redirect too deep' if limit == 0 + + url = URI.parse(url_str) + path = url.path + options + + if is_delete + req = Net::HTTP::Delete.new(path, headers) + else + req = Net::HTTP::Get.new(path, headers) + end + + http = Net::HTTP.start(url.host, url.port, use_ssl: true) + if @debug + http.set_debug_output($stdout) + end + http.read_timeout = 5*60 + resp = http.request(req) + + case resp + when Net::HTTPSuccess then resp + when Net::HTTPRedirection then + call_api(resp['location'], headers, is_delete, options, limit - 1) + else + resp.error! + end + end + # The "POST" method; handles shuttling up encoded job data to Gengo # for translation and such. Somewhat similar to the above methods, but depending on the scenario # can get some strange exceptions, so we're gonna keep them fairly separate for the time being. Consider diff --git a/spec/api_redirect_spec.rb b/spec/api_redirect_spec.rb new file mode 100644 index 0000000..e1ab093 --- /dev/null +++ b/spec/api_redirect_spec.rb @@ -0,0 +1,40 @@ +=begin + + This is a spec that tests calls to account + +=end + +require 'spec_helper' +require 'gengo' +require 'client_context' + +describe Gengo::API do + include_context 'client spec' + + describe "getTranslationOrderJobs" do + it "should call redirected destination" do + public_key = 'pubkeyfortests' + private_key = 'privatekeyfortestuserthatcontainsonlyletters' + + query = {:api_key => public_key, :ts => Time.now.gmtime.to_i.to_s} + + endpoint = "translate/order/10" + url_str = "https://api.gengo.dev/v2/" + endpoint + + options = "?api_sig=" + (OpenSSL::HMAC.hexdigest 'sha1', private_key, query[:ts]) + options << '&' + query.map { |k, v| "#{k}=#{CGI::escape(v)}" }.join('&') + headers = { + 'Accept' => 'application/json', + 'User-Agent' => 'RSpec test', + } + + stub_request(:get, url_str + options) + .to_return(status: 302, headers: {'Location' => 'https://api.gengo.dev/', 'Content-Type' => 'text/html'}) + stub_request(:get, "https://api.gengo.dev/" + options) + .to_return(body: 'contents', headers: {'Content-Type' => 'text/html' }) + + expect(@gengo_client).to receive(:call_api).and_call_original.twice + @gengo_client.call_api(url_str, headers, false, options) + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 8b3bdc5..2e6c98e 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,8 +1,11 @@ require 'rubygems' require 'bundler/setup' +require 'webmock/rspec' require 'gengo' # and any other gems you need RSpec.configure do |config| # some (optional) config here end + +WebMock.allow_net_connect!