From 1c0360f88f3696ac4a426589b79e5a118aa741c4 Mon Sep 17 00:00:00 2001 From: John Nunemaker Date: Sat, 13 May 2017 14:31:55 -0400 Subject: [PATCH 1/6] Allow setting debug output to STDOUT for http client --- lib/flipper/adapters/http/client.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/flipper/adapters/http/client.rb b/lib/flipper/adapters/http/client.rb index ff5b66f99..a968f98d4 100644 --- a/lib/flipper/adapters/http/client.rb +++ b/lib/flipper/adapters/http/client.rb @@ -21,6 +21,7 @@ def initialize(options = {}) @basic_auth_password = options[:basic_auth_password] @read_timeout = options[:read_timeout] @open_timeout = options[:open_timeout] + @debug = options[:debug] end def get(path) @@ -54,6 +55,7 @@ def uri_for_path(path) def build_http(uri) http = Net::HTTP.new(uri.host, uri.port) + http.set_debug_output(STDOUT) if @debug http.read_timeout = @read_timeout if @read_timeout http.open_timeout = @open_timeout if @open_timeout From b2781ddeb821737d0120e544029b1e4fced693e0 Mon Sep 17 00:00:00 2001 From: John Nunemaker Date: Sat, 13 May 2017 14:32:12 -0400 Subject: [PATCH 2/6] Allow passing debug to client from http adapter --- lib/flipper/adapters/http.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/flipper/adapters/http.rb b/lib/flipper/adapters/http.rb index 3370c5eae..c0b9aaa14 100644 --- a/lib/flipper/adapters/http.rb +++ b/lib/flipper/adapters/http.rb @@ -18,7 +18,8 @@ def initialize(options = {}) basic_auth_username: options[:basic_auth_username], basic_auth_password: options[:basic_auth_password], read_timeout: options[:read_timeout], - open_timeout: options[:open_timeout]) + open_timeout: options[:open_timeout], + debug: options[:debug]) @name = :http end From c661e1465e59e8af32aa97387d3a6afc4089c06a Mon Sep 17 00:00:00 2001 From: John Nunemaker Date: Sat, 13 May 2017 14:32:29 -0400 Subject: [PATCH 3/6] Allow passing debug and read/open timeouts from cloud to http adapter --- lib/flipper/cloud.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/flipper/cloud.rb b/lib/flipper/cloud.rb index 4947ba9bf..43dac7f9e 100644 --- a/lib/flipper/cloud.rb +++ b/lib/flipper/cloud.rb @@ -29,6 +29,9 @@ def self.new(token, options = {}) headers: { "Feature-Flipper-Token" => token, }, + read_timeout: options[:read_timeout], + open_timeout: options[:open_timeout], + debug: options[:debug], } adapter = Flipper::Adapters::Http.new(http_options) From 1ffdea18a5c0a6c34b6649c10c52c243aa4f0d1d Mon Sep 17 00:00:00 2001 From: John Nunemaker Date: Mon, 15 May 2017 10:29:15 -0400 Subject: [PATCH 4/6] Remove duplicate debug output from previous commit --- lib/flipper/adapters/http/client.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/flipper/adapters/http/client.rb b/lib/flipper/adapters/http/client.rb index 86e339f3b..11350ea1f 100644 --- a/lib/flipper/adapters/http/client.rb +++ b/lib/flipper/adapters/http/client.rb @@ -55,7 +55,6 @@ def uri_for_path(path) def build_http(uri) http = Net::HTTP.new(uri.host, uri.port) - http.set_debug_output(STDOUT) if @debug http.read_timeout = @read_timeout if @read_timeout http.open_timeout = @open_timeout if @open_timeout http.set_debug_output(@debug_output) if @debug_output From 9c844659737d856d38e7f5badfdefe048b40950f Mon Sep 17 00:00:00 2001 From: John Nunemaker Date: Mon, 15 May 2017 10:30:14 -0400 Subject: [PATCH 5/6] Add open and read timeout specs --- spec/flipper/cloud_spec.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/spec/flipper/cloud_spec.rb b/spec/flipper/cloud_spec.rb index 99a117740..ee176feab 100644 --- a/spec/flipper/cloud_spec.rb +++ b/spec/flipper/cloud_spec.rb @@ -74,4 +74,16 @@ .with(hash_including(debug_output: STDOUT)) described_class.new('asdf', debug_output: STDOUT) end + + it 'can set read_timeout' do + expect(Flipper::Adapters::Http::Client).to receive(:new) + .with(hash_including(read_timeout: 1)) + described_class.new('asdf', read_timeout: 1) + end + + it 'can set open_timeout' do + expect(Flipper::Adapters::Http::Client).to receive(:new) + .with(hash_including(open_timeout: 1)) + described_class.new('asdf', open_timeout: 1) + end end From af530e70b286b0edd24bab95cad992dcfd2e9a59 Mon Sep 17 00:00:00 2001 From: John Nunemaker Date: Tue, 16 May 2017 11:46:47 -0400 Subject: [PATCH 6/6] Allow customizing env key for middleware To avoid env keys hitting up against each other when using these in odd ways like I do... :D --- lib/flipper/api.rb | 9 +++++---- lib/flipper/api/middleware.rb | 5 +++-- lib/flipper/middleware/memoizer.rb | 3 ++- lib/flipper/middleware/setup_env.rb | 5 +++-- lib/flipper/ui.rb | 9 +++++---- lib/flipper/ui/middleware.rb | 5 +++-- spec/flipper/api_spec.rb | 24 ++++++++++++++++++++++++ spec/support/spec_helpers.rb | 8 ++++---- 8 files changed, 49 insertions(+), 19 deletions(-) diff --git a/lib/flipper/api.rb b/lib/flipper/api.rb index 69fadf40d..df1248608 100644 --- a/lib/flipper/api.rb +++ b/lib/flipper/api.rb @@ -9,14 +9,15 @@ module Flipper module Api CONTENT_TYPE = 'application/json'.freeze - def self.app(flipper = nil) + def self.app(flipper = nil, options = {}) + env_key = options.fetch(:env_key, 'flipper') app = ->(_) { [404, { 'Content-Type'.freeze => CONTENT_TYPE }, ['{}'.freeze]] } builder = Rack::Builder.new yield builder if block_given? - builder.use Flipper::Middleware::SetupEnv, flipper - builder.use Flipper::Middleware::Memoizer builder.use Flipper::Api::JsonParams - builder.use Flipper::Api::Middleware + builder.use Flipper::Middleware::SetupEnv, flipper, env_key: env_key + builder.use Flipper::Middleware::Memoizer, env_key: env_key + builder.use Flipper::Api::Middleware, env_key: env_key builder.run app klass = self builder.define_singleton_method(:inspect) { klass.inspect } # pretty rake routes output diff --git a/lib/flipper/api/middleware.rb b/lib/flipper/api/middleware.rb index a4dcbec9d..820087261 100644 --- a/lib/flipper/api/middleware.rb +++ b/lib/flipper/api/middleware.rb @@ -9,8 +9,9 @@ module Flipper module Api class Middleware - def initialize(app) + def initialize(app, options = {}) @app = app + @env_key = options.fetch(:env_key, 'flipper') @action_collection = ActionCollection.new @action_collection.add Api::V1::Actions::PercentageOfTimeGate @@ -33,7 +34,7 @@ def call!(env) if action_class.nil? @app.call(env) else - flipper = env.fetch('flipper') + flipper = env.fetch(@env_key) action_class.run(flipper, request) end end diff --git a/lib/flipper/middleware/memoizer.rb b/lib/flipper/middleware/memoizer.rb index 35b8eaa2e..46eac3d37 100644 --- a/lib/flipper/middleware/memoizer.rb +++ b/lib/flipper/middleware/memoizer.rb @@ -29,6 +29,7 @@ def initialize(app, opts = {}) @app = app @opts = opts + @env_key = opts.fetch(:env_key, 'flipper') end def call(env) @@ -48,7 +49,7 @@ def skip_memoize?(request) end def memoized_call(env) - flipper = env.fetch('flipper') + flipper = env.fetch(@env_key) original = flipper.adapter.memoizing? flipper.adapter.memoize = true diff --git a/lib/flipper/middleware/setup_env.rb b/lib/flipper/middleware/setup_env.rb index be9603699..6b3b4e38d 100644 --- a/lib/flipper/middleware/setup_env.rb +++ b/lib/flipper/middleware/setup_env.rb @@ -19,8 +19,9 @@ class SetupEnv # # using with a block that yields a flipper instance # use Flipper::Middleware::SetEnv, lambda { Flipper.new(...) } # - def initialize(app, flipper_or_block) + def initialize(app, flipper_or_block, options = {}) @app = app + @env_key = options.fetch(:env_key, 'flipper') if flipper_or_block.respond_to?(:call) @flipper_block = flipper_or_block @@ -30,7 +31,7 @@ def initialize(app, flipper_or_block) end def call(env) - env['flipper'.freeze] ||= flipper + env[@env_key] ||= flipper @app.call(env) end diff --git a/lib/flipper/ui.rb b/lib/flipper/ui.rb index a2f3c791e..76373b9e1 100644 --- a/lib/flipper/ui.rb +++ b/lib/flipper/ui.rb @@ -33,16 +33,17 @@ def self.root @root ||= Pathname(__FILE__).dirname.expand_path.join('ui') end - def self.app(flipper = nil) + def self.app(flipper = nil, options = {}) + env_key = options.fetch(:env_key, 'flipper') app = ->() { [200, { 'Content-Type' => 'text/html' }, ['']] } builder = Rack::Builder.new yield builder if block_given? builder.use Rack::Protection builder.use Rack::Protection::AuthenticityToken builder.use Rack::MethodOverride - builder.use Flipper::Middleware::SetupEnv, flipper - builder.use Flipper::Middleware::Memoizer - builder.use Middleware + builder.use Flipper::Middleware::SetupEnv, flipper, env_key: env_key + builder.use Flipper::Middleware::Memoizer, env_key: env_key + builder.use Middleware, env_key: env_key builder.run app klass = self builder.define_singleton_method(:inspect) { klass.inspect } # pretty rake routes output diff --git a/lib/flipper/ui/middleware.rb b/lib/flipper/ui/middleware.rb index c09c22fe9..2b6819ad7 100644 --- a/lib/flipper/ui/middleware.rb +++ b/lib/flipper/ui/middleware.rb @@ -9,8 +9,9 @@ module Flipper module UI class Middleware - def initialize(app) + def initialize(app, options = {}) @app = app + @env_key = options.fetch(:env_key, 'flipper') @action_collection = ActionCollection.new @@ -43,7 +44,7 @@ def call!(env) if action_class.nil? @app.call(env) else - flipper = env.fetch('flipper') + flipper = env.fetch(@env_key) action_class.run(flipper, request) end end diff --git a/spec/flipper/api_spec.rb b/spec/flipper/api_spec.rb index 13b61e3fd..e22ffb6ac 100644 --- a/spec/flipper/api_spec.rb +++ b/spec/flipper/api_spec.rb @@ -43,6 +43,30 @@ end end + context 'when initialized with env_key' do + let(:app) { build_api(flipper, env_key: 'flipper_api') } + + it 'uses provided env key instead of default' do + flipper[:a].enable + flipper[:b].disable + + default_env_flipper = build_flipper + default_env_flipper[:env_a].enable + default_env_flipper[:env_b].disable + + params = {} + env = { + 'flipper' => default_env_flipper, + 'flipper_api' => flipper, + } + get '/features', params, env + + expect(last_response.status).to eq(200) + feature_names = json_response.fetch('features').map { |feature| feature.fetch('key') } + expect(feature_names).to eq(%w(a b)) + end + end + context "when request does not match any api routes" do let(:app) { build_api(flipper) } diff --git a/spec/support/spec_helpers.rb b/spec/support/spec_helpers.rb index d6ec9e809..fc3d2305a 100644 --- a/spec/support/spec_helpers.rb +++ b/spec/support/spec_helpers.rb @@ -8,14 +8,14 @@ def self.included(base) base.let(:app) { build_app(flipper) } end - def build_app(flipper) - Flipper::UI.app(flipper) do |builder| + def build_app(flipper, options = {}) + Flipper::UI.app(flipper, options) do |builder| builder.use Rack::Session::Cookie, secret: 'test' end end - def build_api(flipper) - Flipper::Api.app(flipper) + def build_api(flipper, options = {}) + Flipper::Api.app(flipper, options) end def build_flipper(adapter = build_memory_adapter)