From 8aa50442ab92b4789a8f93532c5aa40e4fecddf3 Mon Sep 17 00:00:00 2001 From: Steven Bazyl Date: Wed, 19 Jun 2013 17:37:38 -0700 Subject: [PATCH] Enable gzip compression --- lib/google/api_client.rb | 9 ++- lib/google/api_client/gzip.rb | 28 ++++++++++ spec/google/api_client/gzip_spec.rb | 86 +++++++++++++++++++++++++++++ 3 files changed, 120 insertions(+), 3 deletions(-) create mode 100644 lib/google/api_client/gzip.rb create mode 100644 spec/google/api_client/gzip_spec.rb diff --git a/lib/google/api_client.rb b/lib/google/api_client.rb index 5261f6afb..f3d1f521a 100644 --- a/lib/google/api_client.rb +++ b/lib/google/api_client.rb @@ -30,6 +30,7 @@ require 'google/api_client/result' require 'google/api_client/media' require 'google/api_client/service_account' require 'google/api_client/batch' +require 'google/api_client/gzip' require 'google/api_client/railtie' if defined?(Rails::Railtie) module Google @@ -97,8 +98,7 @@ module Google end self.user_agent = options[:user_agent] || ( "#{application_string} " + - "google-api-ruby-client/#{Google::APIClient::VERSION::STRING} " + - ENV::OS_VERSION + "google-api-ruby-client/#{Google::APIClient::VERSION::STRING} #{ENV::OS_VERSION} (gzip)" ).strip # The writer method understands a few Symbols and will generate useful # default authentication mechanisms. @@ -112,6 +112,7 @@ module Google @discovered_apis = {} ca_file = options[:ca_file] || File.expand_path('../../cacerts.pem', __FILE__) self.connection = Faraday.new do |faraday| + faraday.response :gzip faraday.options.params_encoder = Faraday::FlatParamsEncoder faraday.ssl.ca_file = ca_file faraday.ssl.verify = true @@ -176,7 +177,6 @@ module Google return @authorization end - ## # Default Faraday/HTTP connection. # @@ -531,6 +531,8 @@ module Google # - (TrueClass, FalseClass) :authenticated (default: true) - # `true` if the request must be signed or somehow # authenticated, `false` otherwise. + # - (TrueClass, FalseClass) :gzip (default: true) - + # `true` if gzip enabled, `false` otherwise. # # @return [Google::APIClient::Result] The result from the API, nil if batch. # @@ -569,6 +571,7 @@ module Google end request.headers['User-Agent'] ||= '' + self.user_agent unless self.user_agent.nil? + request.headers['Accept-Encoding'] ||= 'gzip' unless options[:gzip] == false request.parameters['key'] ||= self.key unless self.key.nil? request.parameters['userIp'] ||= self.user_ip unless self.user_ip.nil? diff --git a/lib/google/api_client/gzip.rb b/lib/google/api_client/gzip.rb new file mode 100644 index 000000000..42fabbbdb --- /dev/null +++ b/lib/google/api_client/gzip.rb @@ -0,0 +1,28 @@ +require 'faraday' +require 'zlib' + +module Google + class APIClient + class Gzip < Faraday::Response::Middleware + include Google::APIClient::Logging + + def on_complete(env) + encoding = env[:response_headers]['content-encoding'].to_s.downcase + case encoding + when 'gzip' + logger.debug { "Decompressing gzip encoded response (#{env[:body].length} bytes)" } + env[:body] = Zlib::GzipReader.new(StringIO.new(env[:body])).read + env[:response_headers].delete('content-encoding') + logger.debug { "Decompressed (#{env[:body].length} bytes)" } + when 'deflate' + logger.debug{ "Decompressing deflate encoded response (#{env[:body].length} bytes)" } + env[:body] = Zlib::Inflate.inflate(env[:body]) + env[:response_headers].delete('content-encoding') + logger.debug { "Decompressed (#{env[:body].length} bytes)" } + end + end + end + end +end + +Faraday::Response.register_middleware :gzip => Google::APIClient::Gzip \ No newline at end of file diff --git a/spec/google/api_client/gzip_spec.rb b/spec/google/api_client/gzip_spec.rb new file mode 100644 index 000000000..bf5be8d02 --- /dev/null +++ b/spec/google/api_client/gzip_spec.rb @@ -0,0 +1,86 @@ +# Copyright 2012 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +require 'spec_helper' + +require 'google/api_client' +require 'google/api_client/version' + +describe Google::APIClient::Gzip do + + def create_connection(&block) + Faraday.new do |b| + b.response :gzip + b.adapter :test do |stub| + stub.get '/', &block + end + end + end + + it 'should ignore non-zipped content' do + conn = create_connection do |env| + [200, {}, 'Hello world'] + end + result = conn.get('/') + result.body.should == "Hello world" + end + + it 'should decompress gziped content' do + conn = create_connection do |env| + [200, { 'Content-Encoding' => 'gzip'}, Base64.decode64('H4sICLVGwlEAA3RtcADzSM3JyVcozy/KSeECANXgObcMAAAA')] + end + result = conn.get('/') + result.body.should == "Hello world\n" + end + + describe 'with API Client' do + + before do + @client = Google::APIClient.new(:application_name => 'test') + @client.authorization = nil + end + + + it 'should send gzip in user agent' do + conn = create_connection do |env| + agent = env[:request_headers]['User-Agent'] + agent.should_not be_nil + agent.should include 'gzip' + [200, {}, 'Hello world'] + end + @client.execute(:uri => 'http://www.example.com/', :connection => conn) + end + + it 'should send gzip in accept-encoding' do + conn = create_connection do |env| + encoding = env[:request_headers]['Accept-Encoding'] + encoding.should_not be_nil + encoding.should include 'gzip' + [200, {}, 'Hello world'] + end + @client.execute(:uri => 'http://www.example.com/', :connection => conn) + end + + it 'should not send gzip in accept-encoding if disabled for request' do + conn = create_connection do |env| + encoding = env[:request_headers]['Accept-Encoding'] + encoding.should_not include('gzip') unless encoding.nil? + [200, {}, 'Hello world'] + end + response = @client.execute(:uri => 'http://www.example.com/', :gzip => false, :connection => conn) + puts response.status + end + + end +end