From ab2c8349d8b66c5efdb2e3cb6e752e4cee73f44d Mon Sep 17 00:00:00 2001 From: Mark Murphy Date: Tue, 17 Feb 2026 13:43:36 -0500 Subject: [PATCH 1/7] Update dependencies and middleware for Faraday integration - Updated Faraday dependency to version >= 2.14 and removed Faraday Middleware. - Refactored connection and middleware classes to use the new Faraday request authorization method. - Adjusted tests to reflect changes in middleware expectations. --- .circleci/config.yml | 19 +++++++++++++++++++ DEPENDENCIES.md | 1 - bigcommerce.gemspec | 3 +-- lib/bigcommerce.rb | 2 +- lib/bigcommerce/connection.rb | 3 +-- lib/bigcommerce/middleware/auth.rb | 4 +--- lib/bigcommerce/middleware/http_exception.rb | 8 +++++++- spec/bigcommerce/bigcommerce_spec.rb | 4 ++-- 8 files changed, 32 insertions(+), 12 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 174a737..0015fce 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -31,6 +31,12 @@ ruby_3_2_defaults: &ruby_3_2_defaults name: ruby/ruby ruby-version: '3.2' +ruby_3_4_defaults: &ruby_3_4_defaults + <<: *defaults + e: + name: ruby/ruby + ruby-version: '3.4' + workflows: version: 2 ruby_2_7: @@ -84,3 +90,16 @@ workflows: name: ruby-3_2-rspec_unit db: false code-climate: false + ruby_3_4: + jobs: + - ruby/bundle-audit: + <<: *ruby_3_4_defaults + name: ruby-3_4-bundle_audit + - ruby/rubocop: + <<: *ruby_3_4_defaults + name: ruby-3_4-rubocop + - ruby/rspec-unit: + <<: *ruby_3_4_defaults + name: ruby-3_4-rspec_unit + db: false + code-climate: false diff --git a/DEPENDENCIES.md b/DEPENDENCIES.md index c0cdf75..11c3ec6 100644 --- a/DEPENDENCIES.md +++ b/DEPENDENCIES.md @@ -3,6 +3,5 @@ Many thanks to the contributors and authors of the following libraries! - [Faraday](https://github.com/lostisland/faraday) Simple, but flexible HTTP client library, with support for multiple backends. - [MIT](https://github.com/lostisland/faraday/blob/master/LICENSE.md) -- [Faraday Middleware](https://github.com/lostisland/faraday_middleware) Various Faraday middlewares for Faraday-based API wrappers. - [MIT](https://github.com/lostisland/faraday_middleware/blob/master/LICENSE.md) - [Hashie](https://github.com/intridea/hashie) Hashie is a collection of classes and mixins that make hashes more powerful. - [MIT](https://github.com/intridea/hashie/blob/master/LICENSE) - [JWT](https://github.com/jwt/ruby-jwt) Used to encode and sign JWT tokens for the Customer Login API. - [MIT](https://github.com/jwt/ruby-jwt/blob/master/LICENSE) diff --git a/bigcommerce.gemspec b/bigcommerce.gemspec index 6227472..79e7f51 100644 --- a/bigcommerce.gemspec +++ b/bigcommerce.gemspec @@ -19,8 +19,7 @@ Gem::Specification.new do |s| s.require_paths = ['lib'] s.files = Dir['README.md', 'lib/**/*', 'bigcommerce.gemspec'] - s.add_dependency 'faraday', '~> 1.1.0' - s.add_dependency 'faraday_middleware', '~> 1.0' + s.add_dependency 'faraday', '>= 2.14', '< 3.0' s.add_dependency 'hashie', '>= 3.4', '~> 4' s.add_dependency 'jwt', '>= 1.5.4', '~> 2' end diff --git a/lib/bigcommerce.rb b/lib/bigcommerce.rb index 71e10f9..0e5edd2 100644 --- a/lib/bigcommerce.rb +++ b/lib/bigcommerce.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true require 'hashie' -require 'faraday_middleware' +require 'faraday' require_relative 'bigcommerce/version' require_relative 'bigcommerce/config' require_relative 'bigcommerce/connection' diff --git a/lib/bigcommerce/connection.rb b/lib/bigcommerce/connection.rb index 7e8b08e..17863d5 100644 --- a/lib/bigcommerce/connection.rb +++ b/lib/bigcommerce/connection.rb @@ -16,12 +16,11 @@ def self.build(config) conn.request :json conn.headers = HEADERS if config.auth == LEGACY_AUTH_MODE - conn.use Faraday::Request::BasicAuthentication, config.username, config.api_key + conn.request :authorization, :basic, config.username, config.api_key else conn.use Bigcommerce::Middleware::Auth, config end conn.use Bigcommerce::Middleware::HttpException - conn.use FaradayMiddleware::Gzip conn.adapter Faraday.default_adapter end end diff --git a/lib/bigcommerce/middleware/auth.rb b/lib/bigcommerce/middleware/auth.rb index 89329f8..d0705e1 100644 --- a/lib/bigcommerce/middleware/auth.rb +++ b/lib/bigcommerce/middleware/auth.rb @@ -7,9 +7,7 @@ class Auth < Faraday::Middleware X_AUTH_TOKEN_HEADER = 'X-Auth-Token' def initialize(app, options = {}) - @app = app - @options = options - super(app) + super end def call(env) diff --git a/lib/bigcommerce/middleware/http_exception.rb b/lib/bigcommerce/middleware/http_exception.rb index c0dcc45..12c45dd 100644 --- a/lib/bigcommerce/middleware/http_exception.rb +++ b/lib/bigcommerce/middleware/http_exception.rb @@ -4,9 +4,15 @@ module Bigcommerce module Middleware - class HttpException < Faraday::Response::Middleware + class HttpException < Faraday::Middleware include Bigcommerce::HttpErrors + def call(env) + @app.call(env).on_complete do |response_env| + on_complete(response_env) + end + end + def on_complete(env) throw_http_exception! env[:status].to_i, env env diff --git a/spec/bigcommerce/bigcommerce_spec.rb b/spec/bigcommerce/bigcommerce_spec.rb index 67c9a09..fd6e969 100644 --- a/spec/bigcommerce/bigcommerce_spec.rb +++ b/spec/bigcommerce/bigcommerce_spec.rb @@ -27,7 +27,7 @@ end it 'should have the correct auth middleware' do - expect(middleware).to include(Faraday::Request::BasicAuthentication) + expect(middleware).to include(Faraday::Request::Authorization) end end @@ -61,7 +61,7 @@ expect(Bigcommerce.api.instance_variable_get('@builder') .instance_variable_get('@handlers')) - .to include(Faraday::Request::BasicAuthentication) + .to include(Faraday::Request::Authorization) Bigcommerce.configure do |config| config.access_token = 'jksdgkjbhksjdb' From 91c6c7b68fb2f366d1e2fcc6522b1e072c079394 Mon Sep 17 00:00:00 2001 From: Mark Murphy Date: Tue, 17 Feb 2026 13:47:56 -0500 Subject: [PATCH 2/7] Remove Ruby 2.7 configuration from CircleCI config and retain Ruby 3.0 settings --- .circleci/config.yml | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 0015fce..f0c10ef 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -7,12 +7,6 @@ orbs: defaults: &defaults notify_failure: false -ruby_2_7_defaults: &ruby_2_7_defaults - <<: *defaults - e: - name: ruby/ruby - ruby-version: '2.7' - ruby_3_0_defaults: &ruby_3_0_defaults <<: *defaults e: @@ -39,19 +33,6 @@ ruby_3_4_defaults: &ruby_3_4_defaults workflows: version: 2 - ruby_2_7: - jobs: - - ruby/bundle-audit: - <<: *ruby_2_7_defaults - name: ruby-2_7-bundle_audit - - ruby/rubocop: - <<: *ruby_2_7_defaults - name: ruby-2_7-rubocop - - ruby/rspec-unit: - <<: *ruby_2_7_defaults - name: ruby-2_7-rspec_unit - db: false - code-climate: false ruby_3_0: jobs: - ruby/bundle-audit: From 8ff77ca3dba027242ca2a49c18bddfd5cb413072 Mon Sep 17 00:00:00 2001 From: Mark Murphy Date: Wed, 18 Feb 2026 16:09:56 -0500 Subject: [PATCH 3/7] Refactor Bigcommerce middleware to support string keys in options - Updated the `call` method to use a new private method `option_value` for retrieving options, allowing for both symbol and string keys. - Added tests to ensure correct header setting when options are provided with string keys. --- lib/bigcommerce/middleware/auth.rb | 10 ++++++++-- spec/bigcommerce/unit/middleware/auth_spec.rb | 20 +++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/lib/bigcommerce/middleware/auth.rb b/lib/bigcommerce/middleware/auth.rb index d0705e1..c501127 100644 --- a/lib/bigcommerce/middleware/auth.rb +++ b/lib/bigcommerce/middleware/auth.rb @@ -11,10 +11,16 @@ def initialize(app, options = {}) end def call(env) - env[:request_headers][X_AUTH_CLIENT_HEADER] = @options[:client_id] - env[:request_headers][X_AUTH_TOKEN_HEADER] = @options[:access_token] + env[:request_headers][X_AUTH_CLIENT_HEADER] = option_value(:client_id) + env[:request_headers][X_AUTH_TOKEN_HEADER] = option_value(:access_token) @app.call env end + + private + + def option_value(key) + @options[key] || @options[key.to_s] + end end end end diff --git a/spec/bigcommerce/unit/middleware/auth_spec.rb b/spec/bigcommerce/unit/middleware/auth_spec.rb index a623047..570691c 100644 --- a/spec/bigcommerce/unit/middleware/auth_spec.rb +++ b/spec/bigcommerce/unit/middleware/auth_spec.rb @@ -27,5 +27,25 @@ expect(app).to receive(:call).with(expected_hash) subject end + + context 'when options use string keys' do + let(:options) do + { + 'client_id' => client_id, + 'access_token' => client_token + } + end + + it 'sets the correct headers' do + expected_hash = { + request_headers: { + 'X-Auth-Client' => client_id, + 'X-Auth-Token' => client_token + } + } + expect(app).to receive(:call).with(expected_hash) + subject + end + end end end From d2cf8fc1aff2f75aaafcf186ae33ef1cf3c9b11d Mon Sep 17 00:00:00 2001 From: Mark Murphy Date: Wed, 18 Feb 2026 16:40:01 -0500 Subject: [PATCH 4/7] Enhance Bigcommerce request handling for gzip encoded responses - Updated the `parse` method to handle gzip encoded JSON responses by adding a `decode_body` method. - Modified the `build_response_object` method to pass response headers to the `parse` method. - Added tests to verify the correct decoding and object building for gzip encoded responses. --- lib/bigcommerce/request.rb | 20 +++++++++++++++++--- spec/bigcommerce/unit/request_spec.rb | 25 +++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/lib/bigcommerce/request.rb b/lib/bigcommerce/request.rb index 2bfd577..71e026a 100644 --- a/lib/bigcommerce/request.rb +++ b/lib/bigcommerce/request.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true require 'json' +require 'stringio' +require 'zlib' module Bigcommerce class Request < Module @@ -46,7 +48,7 @@ def raw_request(method, path, params = {}) private def build_response_object(response) - json = parse response.body + json = parse(response.body, response.headers) if json.is_a? Array json.map { |obj| new obj } else @@ -58,10 +60,22 @@ def build_response_object(response) # @return [Hash] # @return [Array] # - def parse(json) + def parse(json, headers = {}) return [] if json.empty? - JSON.parse(json, symbolize_names: true) + JSON.parse(decode_body(json, headers), symbolize_names: true) + end + + def decode_body(body, headers = {}) + payload = body.to_s.dup.force_encoding(Encoding::BINARY) + return payload if payload.empty? + + content_encoding = headers['content-encoding'] || headers[:content_encoding] + return payload unless content_encoding.to_s.downcase.include?('gzip') || payload.start_with?("\x1F\x8B".b) + + Zlib::GzipReader.new(StringIO.new(payload)).read + rescue Zlib::Error + payload end end end diff --git a/spec/bigcommerce/unit/request_spec.rb b/spec/bigcommerce/unit/request_spec.rb index 4768ba5..c1c6cc3 100644 --- a/spec/bigcommerce/unit/request_spec.rb +++ b/spec/bigcommerce/unit/request_spec.rb @@ -1,5 +1,8 @@ # frozen_string_literal: true +require 'stringio' +require 'zlib' + RSpec.describe Bigcommerce::Request do before do module Bigcommerce @@ -98,6 +101,7 @@ def initialize(params) it 'should build an array of objects' do response = double allow(response).to receive(:body) { json } + allow(response).to receive(:headers) { {} } objs = @klass_with_init.send(:build_response_object, response) expect(objs).to be_kind_of Array objs.each do |obj| @@ -110,6 +114,27 @@ def initialize(params) it 'should build an object' do response = double allow(response).to receive(:body) { json } + allow(response).to receive(:headers) { {} } + objs = @klass_with_init.send(:build_response_object, response) + expect(objs).to be_kind_of Bigcommerce::DummyClass + end + end + + describe 'gzip encoded json object' do + let(:json) { "{\"time\":1426184190}" } + + def gzip_payload(payload) + io = StringIO.new + gz = Zlib::GzipWriter.new(io) + gz.write(payload) + gz.close + io.string + end + + it 'should decode and build an object' do + response = double + allow(response).to receive(:body) { gzip_payload(json) } + allow(response).to receive(:headers) { { 'content-encoding' => 'gzip' } } objs = @klass_with_init.send(:build_response_object, response) expect(objs).to be_kind_of Bigcommerce::DummyClass end From 2a077890abcf70ab86854df740ca5e8491af2177 Mon Sep 17 00:00:00 2001 From: Mark Murphy Date: Wed, 18 Feb 2026 16:52:44 -0500 Subject: [PATCH 5/7] fix: address PR review bot findings - chatgpt-codex-connector[bot]: restore gzip decoding for raw_request and delete responses - add unit coverage for gzip decoding in delete and raw_request --- lib/bigcommerce/request.rb | 8 +++-- spec/bigcommerce/unit/request_spec.rb | 47 ++++++++++++++++++++++----- 2 files changed, 45 insertions(+), 10 deletions(-) diff --git a/lib/bigcommerce/request.rb b/lib/bigcommerce/request.rb index 71e026a..1c0bbfa 100644 --- a/lib/bigcommerce/request.rb +++ b/lib/bigcommerce/request.rb @@ -27,7 +27,7 @@ def get(path, params = {}) def delete(path, params = {}) response = raw_request(:delete, path, params) - response.body + decode_body(response.body, response.headers) end def post(path, params = {}) @@ -42,7 +42,11 @@ def put(path, params = {}) def raw_request(method, path, params = {}) client = params.delete(:connection) || Bigcommerce.api - client.send(method, path.to_s, params) + response = client.send(method, path.to_s, params) + return response unless response.respond_to?(:body) && response.respond_to?(:body=) + + response.body = decode_body(response.body, response.respond_to?(:headers) ? response.headers : {}) + response end private diff --git a/spec/bigcommerce/unit/request_spec.rb b/spec/bigcommerce/unit/request_spec.rb index c1c6cc3..ef0227b 100644 --- a/spec/bigcommerce/unit/request_spec.rb +++ b/spec/bigcommerce/unit/request_spec.rb @@ -20,6 +20,14 @@ class DummyClass end describe 'ClassMethods' do + def gzip_payload(payload) + io = StringIO.new + gz = Zlib::GzipWriter.new(io) + gz.write(payload) + gz.close + io.string + end + before do double Bigcommerce.api end @@ -39,10 +47,21 @@ class DummyClass it 'should call raw_request' do response = double allow(response).to receive(:body) { '' } + allow(response).to receive(:headers) { {} } allow(@klass).to receive(:raw_request) { response } expect(@klass).to receive(:raw_request).with(:delete, @klass.path, {}) @klass.delete(@klass.path) end + + it 'decodes gzip encoded response bodies' do + payload = '{"ok":true}' + response = double + allow(response).to receive(:body) { gzip_payload(payload) } + allow(response).to receive(:headers) { { 'content-encoding' => 'gzip' } } + allow(@klass).to receive(:raw_request).and_return(response) + + expect(@klass.delete(@klass.path)).to eq(payload) + end end describe '.post' do @@ -79,9 +98,29 @@ class DummyClass expect(@api).to receive(:get).with('path/1', {}) @klass.raw_request(:get, 'path/1') end + + it 'decodes gzip encoded response bodies' do + payload = '{"ok":true}' + response = Struct.new(:body, :headers).new( + gzip_payload(payload), + { 'content-encoding' => 'gzip' } + ) + allow(@api).to receive(:get).and_return(response) + + result = @klass.raw_request(:get, 'path/1') + expect(result.body).to eq(payload) + end end describe 'private methods' do + def gzip_payload(payload) + io = StringIO.new + gz = Zlib::GzipWriter.new(io) + gz.write(payload) + gz.close + io.string + end + describe '.build_response_object' do before do module Bigcommerce @@ -123,14 +162,6 @@ def initialize(params) describe 'gzip encoded json object' do let(:json) { "{\"time\":1426184190}" } - def gzip_payload(payload) - io = StringIO.new - gz = Zlib::GzipWriter.new(io) - gz.write(payload) - gz.close - io.string - end - it 'should decode and build an object' do response = double allow(response).to receive(:body) { gzip_payload(json) } From 0ff8550a30fbbae09a0e5dcd4677cf6f1432aafc Mon Sep 17 00:00:00 2001 From: Mark Murphy Date: Wed, 18 Feb 2026 17:36:14 -0500 Subject: [PATCH 6/7] chore: release version 2.0.0 - Updated version to 2.0.0 in `version.rb`. - Added entry for the release in `CHANGELOG.md`, noting the update to Faraday 2.14 and support for Ruby 3.4. --- CHANGELOG.md | 4 ++++ lib/bigcommerce/version.rb | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 72a9984..be9712c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ Your contribution here. * [#000](https://github.com/bigcommerce/bigcommerce-api-ruby/pull/000): Brief description here. - [@username](https://github.com/username). +## 2.0.0 + +* [#186](https://github.com/bigcommerce/bigcommerce-api-ruby/pull/186): Update to Faraday 2.14 and add support for Ruby 3.4 - [@markcmurphy](https://github.com/markcmurphy). + ## 1.1.0 * [#174](https://github.com/bigcommerce/bigcommerce-api-ruby/pull/174): Drop support for ruby 2.6; Add support for Ruby 3.2 - [@j05h](https://github.com/j05h). diff --git a/lib/bigcommerce/version.rb b/lib/bigcommerce/version.rb index 76a31fc..2cf90b7 100644 --- a/lib/bigcommerce/version.rb +++ b/lib/bigcommerce/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module Bigcommerce - VERSION = '1.1.0' + VERSION = '2.0.0' end From 59925db01fae9ad8949bfa3ed5ffa1485514227f Mon Sep 17 00:00:00 2001 From: Mark Murphy Date: Thu, 19 Feb 2026 11:13:59 -0500 Subject: [PATCH 7/7] feat: add gzip middleware support and update dependencies - Added `faraday-gzip` as a dependency to enable gzip request and response compression. - Updated the Bigcommerce connection to use gzip middleware for requests. - Modified the request handling to simplify response body processing by removing gzip decoding logic. - Updated tests to verify the inclusion of gzip middleware in the request pipeline. --- DEPENDENCIES.md | 1 + bigcommerce.gemspec | 1 + lib/bigcommerce.rb | 1 + lib/bigcommerce/connection.rb | 1 + lib/bigcommerce/middleware/auth.rb | 8 ++-- lib/bigcommerce/request.rb | 28 +++----------- spec/bigcommerce/bigcommerce_spec.rb | 8 ++++ spec/bigcommerce/unit/request_spec.rb | 56 --------------------------- 8 files changed, 20 insertions(+), 84 deletions(-) diff --git a/DEPENDENCIES.md b/DEPENDENCIES.md index 11c3ec6..74a0107 100644 --- a/DEPENDENCIES.md +++ b/DEPENDENCIES.md @@ -3,5 +3,6 @@ Many thanks to the contributors and authors of the following libraries! - [Faraday](https://github.com/lostisland/faraday) Simple, but flexible HTTP client library, with support for multiple backends. - [MIT](https://github.com/lostisland/faraday/blob/master/LICENSE.md) +- [Faraday Gzip](https://github.com/bodrovis/faraday-gzip) Gzip request and response compression middleware for Faraday. - [MIT](https://github.com/bodrovis/faraday-gzip/blob/main/LICENSE.txt) - [Hashie](https://github.com/intridea/hashie) Hashie is a collection of classes and mixins that make hashes more powerful. - [MIT](https://github.com/intridea/hashie/blob/master/LICENSE) - [JWT](https://github.com/jwt/ruby-jwt) Used to encode and sign JWT tokens for the Customer Login API. - [MIT](https://github.com/jwt/ruby-jwt/blob/master/LICENSE) diff --git a/bigcommerce.gemspec b/bigcommerce.gemspec index 79e7f51..0580103 100644 --- a/bigcommerce.gemspec +++ b/bigcommerce.gemspec @@ -20,6 +20,7 @@ Gem::Specification.new do |s| s.files = Dir['README.md', 'lib/**/*', 'bigcommerce.gemspec'] s.add_dependency 'faraday', '>= 2.14', '< 3.0' + s.add_dependency 'faraday-gzip', '~> 3.0' s.add_dependency 'hashie', '>= 3.4', '~> 4' s.add_dependency 'jwt', '>= 1.5.4', '~> 2' end diff --git a/lib/bigcommerce.rb b/lib/bigcommerce.rb index 0e5edd2..b809504 100644 --- a/lib/bigcommerce.rb +++ b/lib/bigcommerce.rb @@ -2,6 +2,7 @@ require 'hashie' require 'faraday' +require 'faraday/gzip' require_relative 'bigcommerce/version' require_relative 'bigcommerce/config' require_relative 'bigcommerce/connection' diff --git a/lib/bigcommerce/connection.rb b/lib/bigcommerce/connection.rb index 17863d5..266a69f 100644 --- a/lib/bigcommerce/connection.rb +++ b/lib/bigcommerce/connection.rb @@ -20,6 +20,7 @@ def self.build(config) else conn.use Bigcommerce::Middleware::Auth, config end + conn.request :gzip conn.use Bigcommerce::Middleware::HttpException conn.adapter Faraday.default_adapter end diff --git a/lib/bigcommerce/middleware/auth.rb b/lib/bigcommerce/middleware/auth.rb index c501127..93b24a9 100644 --- a/lib/bigcommerce/middleware/auth.rb +++ b/lib/bigcommerce/middleware/auth.rb @@ -6,10 +6,6 @@ class Auth < Faraday::Middleware X_AUTH_CLIENT_HEADER = 'X-Auth-Client' X_AUTH_TOKEN_HEADER = 'X-Auth-Token' - def initialize(app, options = {}) - super - end - def call(env) env[:request_headers][X_AUTH_CLIENT_HEADER] = option_value(:client_id) env[:request_headers][X_AUTH_TOKEN_HEADER] = option_value(:access_token) @@ -19,7 +15,9 @@ def call(env) private def option_value(key) - @options[key] || @options[key.to_s] + return @options[key] if @options.key?(key) + + @options[key.to_s] end end end diff --git a/lib/bigcommerce/request.rb b/lib/bigcommerce/request.rb index 1c0bbfa..eed6b3a 100644 --- a/lib/bigcommerce/request.rb +++ b/lib/bigcommerce/request.rb @@ -1,8 +1,6 @@ # frozen_string_literal: true require 'json' -require 'stringio' -require 'zlib' module Bigcommerce class Request < Module @@ -27,7 +25,7 @@ def get(path, params = {}) def delete(path, params = {}) response = raw_request(:delete, path, params) - decode_body(response.body, response.headers) + response.body end def post(path, params = {}) @@ -42,17 +40,13 @@ def put(path, params = {}) def raw_request(method, path, params = {}) client = params.delete(:connection) || Bigcommerce.api - response = client.send(method, path.to_s, params) - return response unless response.respond_to?(:body) && response.respond_to?(:body=) - - response.body = decode_body(response.body, response.respond_to?(:headers) ? response.headers : {}) - response + client.send(method, path.to_s, params) end private def build_response_object(response) - json = parse(response.body, response.headers) + json = parse(response.body) if json.is_a? Array json.map { |obj| new obj } else @@ -64,22 +58,10 @@ def build_response_object(response) # @return [Hash] # @return [Array] # - def parse(json, headers = {}) + def parse(json) return [] if json.empty? - JSON.parse(decode_body(json, headers), symbolize_names: true) - end - - def decode_body(body, headers = {}) - payload = body.to_s.dup.force_encoding(Encoding::BINARY) - return payload if payload.empty? - - content_encoding = headers['content-encoding'] || headers[:content_encoding] - return payload unless content_encoding.to_s.downcase.include?('gzip') || payload.start_with?("\x1F\x8B".b) - - Zlib::GzipReader.new(StringIO.new(payload)).read - rescue Zlib::Error - payload + JSON.parse(json, symbolize_names: true) end end end diff --git a/spec/bigcommerce/bigcommerce_spec.rb b/spec/bigcommerce/bigcommerce_spec.rb index fd6e969..69752fd 100644 --- a/spec/bigcommerce/bigcommerce_spec.rb +++ b/spec/bigcommerce/bigcommerce_spec.rb @@ -29,6 +29,10 @@ it 'should have the correct auth middleware' do expect(middleware).to include(Faraday::Request::Authorization) end + + it 'should include gzip middleware' do + expect(middleware.map(&:klass)).to include(Faraday::Gzip::Middleware) + end end context 'when not using legacy' do @@ -42,6 +46,10 @@ it 'should have the correct auth middleware' do expect(middleware).to include(Bigcommerce::Middleware::Auth) end + + it 'should include gzip middleware' do + expect(middleware.map(&:klass)).to include(Faraday::Gzip::Middleware) + end end end diff --git a/spec/bigcommerce/unit/request_spec.rb b/spec/bigcommerce/unit/request_spec.rb index ef0227b..4768ba5 100644 --- a/spec/bigcommerce/unit/request_spec.rb +++ b/spec/bigcommerce/unit/request_spec.rb @@ -1,8 +1,5 @@ # frozen_string_literal: true -require 'stringio' -require 'zlib' - RSpec.describe Bigcommerce::Request do before do module Bigcommerce @@ -20,14 +17,6 @@ class DummyClass end describe 'ClassMethods' do - def gzip_payload(payload) - io = StringIO.new - gz = Zlib::GzipWriter.new(io) - gz.write(payload) - gz.close - io.string - end - before do double Bigcommerce.api end @@ -47,21 +36,10 @@ def gzip_payload(payload) it 'should call raw_request' do response = double allow(response).to receive(:body) { '' } - allow(response).to receive(:headers) { {} } allow(@klass).to receive(:raw_request) { response } expect(@klass).to receive(:raw_request).with(:delete, @klass.path, {}) @klass.delete(@klass.path) end - - it 'decodes gzip encoded response bodies' do - payload = '{"ok":true}' - response = double - allow(response).to receive(:body) { gzip_payload(payload) } - allow(response).to receive(:headers) { { 'content-encoding' => 'gzip' } } - allow(@klass).to receive(:raw_request).and_return(response) - - expect(@klass.delete(@klass.path)).to eq(payload) - end end describe '.post' do @@ -98,29 +76,9 @@ def gzip_payload(payload) expect(@api).to receive(:get).with('path/1', {}) @klass.raw_request(:get, 'path/1') end - - it 'decodes gzip encoded response bodies' do - payload = '{"ok":true}' - response = Struct.new(:body, :headers).new( - gzip_payload(payload), - { 'content-encoding' => 'gzip' } - ) - allow(@api).to receive(:get).and_return(response) - - result = @klass.raw_request(:get, 'path/1') - expect(result.body).to eq(payload) - end end describe 'private methods' do - def gzip_payload(payload) - io = StringIO.new - gz = Zlib::GzipWriter.new(io) - gz.write(payload) - gz.close - io.string - end - describe '.build_response_object' do before do module Bigcommerce @@ -140,7 +98,6 @@ def initialize(params) it 'should build an array of objects' do response = double allow(response).to receive(:body) { json } - allow(response).to receive(:headers) { {} } objs = @klass_with_init.send(:build_response_object, response) expect(objs).to be_kind_of Array objs.each do |obj| @@ -153,19 +110,6 @@ def initialize(params) it 'should build an object' do response = double allow(response).to receive(:body) { json } - allow(response).to receive(:headers) { {} } - objs = @klass_with_init.send(:build_response_object, response) - expect(objs).to be_kind_of Bigcommerce::DummyClass - end - end - - describe 'gzip encoded json object' do - let(:json) { "{\"time\":1426184190}" } - - it 'should decode and build an object' do - response = double - allow(response).to receive(:body) { gzip_payload(json) } - allow(response).to receive(:headers) { { 'content-encoding' => 'gzip' } } objs = @klass_with_init.send(:build_response_object, response) expect(objs).to be_kind_of Bigcommerce::DummyClass end