flipper-api 0.10.2 → 0.11.0.beta1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/flipper-api.gemspec +12 -12
  3. data/lib/flipper/api/action.rb +12 -10
  4. data/lib/flipper/api/action_collection.rb +2 -2
  5. data/lib/flipper/api/error_response.rb +9 -8
  6. data/lib/flipper/api/json_params.rb +45 -0
  7. data/lib/flipper/api/middleware.rb +3 -28
  8. data/lib/flipper/api/v1/actions/actors_gate.rb +1 -9
  9. data/lib/flipper/api/v1/actions/boolean_gate.rb +1 -1
  10. data/lib/flipper/api/v1/actions/clear_feature.rb +21 -0
  11. data/lib/flipper/api/v1/actions/feature.rb +8 -16
  12. data/lib/flipper/api/v1/actions/features.rb +26 -8
  13. data/lib/flipper/api/v1/actions/groups_gate.rb +18 -7
  14. data/lib/flipper/api/v1/actions/percentage_of_actors_gate.rb +6 -24
  15. data/lib/flipper/api/v1/actions/percentage_of_time_gate.rb +6 -23
  16. data/lib/flipper/api/v1/decorators/feature.rb +3 -4
  17. data/lib/flipper/api.rb +11 -27
  18. data/lib/flipper/version.rb +1 -1
  19. data/spec/flipper/api/action_spec.rb +30 -36
  20. data/spec/flipper/api/json_params_spec.rb +81 -0
  21. data/spec/flipper/api/v1/actions/actors_gate_spec.rb +33 -22
  22. data/spec/flipper/api/v1/actions/boolean_gate_spec.rb +2 -2
  23. data/spec/flipper/api/v1/actions/clear_feature_spec.rb +27 -0
  24. data/spec/flipper/api/v1/actions/feature_spec.rb +28 -30
  25. data/spec/flipper/api/v1/actions/features_spec.rb +79 -44
  26. data/spec/flipper/api/v1/actions/groups_gate_spec.rb +92 -10
  27. data/spec/flipper/api/v1/actions/percentage_of_actors_gate_spec.rb +62 -24
  28. data/spec/flipper/api/v1/actions/percentage_of_time_gate_spec.rb +34 -15
  29. data/spec/flipper/api_spec.rb +55 -0
  30. metadata +15 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2930a9c3ee15cd28f92ef28ecb97c05e104d1721
4
- data.tar.gz: 5495a6703ebc072e1f246c69fe9d9b11c811e93d
3
+ metadata.gz: c14f137259ca4f58e82fa3ed35b32dd1f0375cb3
4
+ data.tar.gz: 6ed6d5173f602c198cc7b41e7cc2ac72c9fac096
5
5
  SHA512:
6
- metadata.gz: fd8d1afb98c55d9a52b3bc640092234ca70c4531afad457701ea2d6c7702c88d61f2d71c4af35481a238d1d9ee990f39b6e23d47bbe02aeb6a26d368b3c1c4cf
7
- data.tar.gz: fbfbd9c149177299f004516ce65f6775891c266d7effb923c07af8a660604da1912720af3b39e0103818d65173b79d8fbeccd6ce636bef70c733b410fadee902
6
+ metadata.gz: ffaf1fefc28654784568f600a17f0506a4d0833e4de153aedf89ced7b06613d6a9b7468d400afbdeabf762fd26ca50128140301abeb0e06df1c25c5ed3ef1b0e
7
+ data.tar.gz: 419c2e26875d8973e7c37d8e1258f1fed26809b1d8798cb692d468f79b5de51599ef57205b4309401198e8bd211d891ddaeb6ed244ecdeae6997883c1d4880e0
data/flipper-api.gemspec CHANGED
@@ -1,21 +1,21 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  require File.expand_path('../lib/flipper/version', __FILE__)
3
3
 
4
- flipper_api_files = lambda { |file|
5
- file =~ /(flipper)[\/-]api/
6
- }
4
+ flipper_api_files = lambda do |file|
5
+ file =~ %r{(flipper)[\/-]api}
6
+ end
7
7
 
8
8
  Gem::Specification.new do |gem|
9
- gem.authors = ["John Nunemaker"]
10
- gem.email = ["nunemaker@gmail.com"]
11
- gem.summary = "API for the Flipper gem"
12
- gem.description = "Rack middleware that provides an API for the flipper gem."
13
- gem.license = "MIT"
14
- gem.homepage = "https://github.com/jnunemaker/flipper"
15
- gem.files = `git ls-files`.split("\n").select(&flipper_api_files) + ["lib/flipper/version.rb"]
9
+ gem.authors = ['John Nunemaker']
10
+ gem.email = ['nunemaker@gmail.com']
11
+ gem.summary = 'API for the Flipper gem'
12
+ gem.description = 'Rack middleware that provides an API for the flipper gem.'
13
+ gem.license = 'MIT'
14
+ gem.homepage = 'https://github.com/jnunemaker/flipper'
15
+ gem.files = `git ls-files`.split("\n").select(&flipper_api_files) + ['lib/flipper/version.rb']
16
16
  gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n").select(&flipper_api_files)
17
- gem.name = "flipper-api"
18
- gem.require_paths = ["lib"]
17
+ gem.name = 'flipper-api'
18
+ gem.require_paths = ['lib']
19
19
  gem.version = Flipper::VERSION
20
20
 
21
21
  gem.add_dependency 'rack', '>= 1.4', '< 3'
@@ -9,11 +9,11 @@ module Flipper
9
9
  extend Forwardable
10
10
 
11
11
  VALID_REQUEST_METHOD_NAMES = Set.new([
12
- "get".freeze,
13
- "post".freeze,
14
- "put".freeze,
15
- "delete".freeze,
16
- ]).freeze
12
+ 'get'.freeze,
13
+ 'post'.freeze,
14
+ 'put'.freeze,
15
+ 'delete'.freeze,
16
+ ]).freeze
17
17
 
18
18
  # Public: Call this in subclasses so the action knows its route.
19
19
  #
@@ -50,9 +50,10 @@ module Flipper
50
50
  def_delegator :@request, :params
51
51
 
52
52
  def initialize(flipper, request)
53
- @flipper, @request = flipper, request
53
+ @flipper = flipper
54
+ @request = request
54
55
  @code = 200
55
- @headers = {"Content-Type" => Api::CONTENT_TYPE }
56
+ @headers = { 'Content-Type' => Api::CONTENT_TYPE }
56
57
  end
57
58
 
58
59
  # Public: Runs the request method for the provided request.
@@ -62,7 +63,8 @@ module Flipper
62
63
  if valid_request_method? && respond_to?(request_method_name)
63
64
  catch(:halt) { send(request_method_name) }
64
65
  else
65
- raise Api::RequestMethodNotSupported, "#{self.class} does not support request method #{request_method_name.inspect}"
66
+ raise Api::RequestMethodNotSupported,
67
+ "#{self.class} does not support request method #{request_method_name.inspect}"
66
68
  end
67
69
  end
68
70
 
@@ -135,9 +137,9 @@ module Flipper
135
137
  end
136
138
 
137
139
  # Private: split request path by "/"
138
- # Example: "api/v1/features/feature_name" => ['api', 'v1', 'features', 'feature_name']
140
+ # Example: "features/feature_name" => ['features', 'feature_name']
139
141
  def path_parts
140
- @request.path.split("/")
142
+ @request.path.split('/')
141
143
  end
142
144
 
143
145
  def valid_request_method?
@@ -10,9 +10,9 @@ module Flipper
10
10
  end
11
11
 
12
12
  def action_for_request(request)
13
- @action_classes.detect { |action_class|
13
+ @action_classes.detect do |action_class|
14
14
  request.path_info =~ action_class.regex
15
- }
15
+ end
16
16
  end
17
17
  end
18
18
  end
@@ -7,7 +7,8 @@ module Flipper
7
7
  def initialize(code, message, http_status)
8
8
  @code = code
9
9
  @message = message
10
- @more_info = "https://github.com/jnunemaker/flipper/tree/master/docs/api#error-code-reference"
10
+ @more_info =
11
+ 'https://github.com/jnunemaker/flipper/tree/master/docs/api#error-code-reference'
11
12
  @http_status = http_status
12
13
  end
13
14
 
@@ -21,13 +22,13 @@ module Flipper
21
22
  end
22
23
 
23
24
  ERRORS = {
24
- feature_not_found: Error.new(1, "Feature not found.", 404),
25
- group_not_registered: Error.new(2, "Group not registered.", 404),
26
- percentage_invalid: Error.new(3, "Percentage must be a positive number less than or equal to 100.", 422),
27
- flipper_id_invalid: Error.new(4, "Required parameter flipper_id is missing.", 422),
28
- name_invalid: Error.new(5, "Required parameter name is missing.", 422),
29
- }
30
-
25
+ feature_not_found: Error.new(1, 'Feature not found.', 404),
26
+ group_not_registered: Error.new(2, 'Group not registered.', 404),
27
+ percentage_invalid:
28
+ Error.new(3, 'Percentage must be a positive number less than or equal to 100.', 422),
29
+ flipper_id_invalid: Error.new(4, 'Required parameter flipper_id is missing.', 422),
30
+ name_invalid: Error.new(5, 'Required parameter name is missing.', 422),
31
+ }.freeze
31
32
  end
32
33
  end
33
34
  end
@@ -0,0 +1,45 @@
1
+ require 'rack/utils'
2
+
3
+ module Flipper
4
+ module Api
5
+ class JsonParams
6
+ include Rack::Utils
7
+
8
+ def initialize(app)
9
+ @app = app
10
+ end
11
+
12
+ CONTENT_TYPE = 'CONTENT_TYPE'.freeze
13
+ QUERY_STRING = 'QUERY_STRING'.freeze
14
+ REQUEST_BODY = 'rack.input'.freeze
15
+
16
+ # Public: Merge request body params with query string params
17
+ # This way can access all params with Rack::Request#params
18
+ # Rack does not add application/json params to Rack::Request#params
19
+ # Allows app to handle x-www-url-form-encoded / application/json request
20
+ # parameters the same way
21
+ def call(env)
22
+ if env[CONTENT_TYPE] == 'application/json'
23
+ body = env[REQUEST_BODY].read
24
+ env[REQUEST_BODY].rewind
25
+ update_params(env, body)
26
+ end
27
+ @app.call(env)
28
+ end
29
+
30
+ private
31
+
32
+ # Rails 3.2.2.1 Rack version does not have Rack::Request#update_param
33
+ # Rack 1.5.0 adds update_param
34
+ # This method accomplishes similar functionality
35
+ def update_params(env, data)
36
+ return if data.empty?
37
+ parsed_request_body = JSON.parse(data)
38
+ parsed_query_string = parse_query(env[QUERY_STRING])
39
+ parsed_query_string.merge!(parsed_request_body)
40
+ parameters = build_query(parsed_query_string)
41
+ env[QUERY_STRING] = parameters
42
+ end
43
+ end
44
+ end
45
+ end
@@ -9,45 +9,20 @@ end
9
9
  module Flipper
10
10
  module Api
11
11
  class Middleware
12
- # Public: Initializes an instance of the API middleware.
13
- #
14
- # app - The app this middleware is included in.
15
- # flipper_or_block - The Flipper::DSL instance or a block that yields a
16
- # Flipper::DSL instance to use for all operations.
17
- #
18
- # Examples
19
- #
20
- # flipper = Flipper.new(...)
21
- #
22
- # # using with a normal flipper instance
23
- # use Flipper::Api::Middleware, flipper
24
- #
25
- # # using with a block that yields a flipper instance
26
- # use Flipper::Api::Middleware, lambda { Flipper.new(...) }
27
- #
28
- def initialize(app, flipper_or_block)
12
+ def initialize(app)
29
13
  @app = app
30
14
 
31
- if flipper_or_block.respond_to?(:call)
32
- @flipper_block = flipper_or_block
33
- else
34
- @flipper = flipper_or_block
35
- end
36
-
37
15
  @action_collection = ActionCollection.new
38
16
  @action_collection.add Api::V1::Actions::PercentageOfTimeGate
39
17
  @action_collection.add Api::V1::Actions::PercentageOfActorsGate
40
18
  @action_collection.add Api::V1::Actions::ActorsGate
41
19
  @action_collection.add Api::V1::Actions::GroupsGate
42
20
  @action_collection.add Api::V1::Actions::BooleanGate
21
+ @action_collection.add Api::V1::Actions::ClearFeature
43
22
  @action_collection.add Api::V1::Actions::Feature
44
23
  @action_collection.add Api::V1::Actions::Features
45
24
  end
46
25
 
47
- def flipper
48
- @flipper ||= @flipper_block.call
49
- end
50
-
51
26
  def call(env)
52
27
  dup.call!(env)
53
28
  end
@@ -56,9 +31,9 @@ module Flipper
56
31
  request = Rack::Request.new(env)
57
32
  action_class = @action_collection.action_for_request(request)
58
33
  if action_class.nil?
59
- @app.status = 404
60
34
  @app.call(env)
61
35
  else
36
+ flipper = env.fetch('flipper')
62
37
  action_class.run(flipper, request)
63
38
  end
64
39
  end
@@ -6,7 +6,7 @@ module Flipper
6
6
  module V1
7
7
  module Actions
8
8
  class ActorsGate < Api::Action
9
- route %r{api/v1/features/[^/]*/actors/?\Z}
9
+ route %r{features/[^/]*/actors/?\Z}
10
10
 
11
11
  def post
12
12
  ensure_valid_params
@@ -29,10 +29,6 @@ module Flipper
29
29
  private
30
30
 
31
31
  def ensure_valid_params
32
- unless feature_names.include?(feature_name)
33
- json_error_response(:feature_not_found)
34
- end
35
-
36
32
  json_error_response(:flipper_id_invalid) if flipper_id.nil?
37
33
  end
38
34
 
@@ -43,10 +39,6 @@ module Flipper
43
39
  def flipper_id
44
40
  @flipper_id ||= params['flipper_id']
45
41
  end
46
-
47
- def feature_names
48
- @feature_names ||= flipper.adapter.features
49
- end
50
42
  end
51
43
  end
52
44
  end
@@ -6,7 +6,7 @@ module Flipper
6
6
  module V1
7
7
  module Actions
8
8
  class BooleanGate < Api::Action
9
- route %r{api/v1/features/[^/]*/boolean/?\Z}
9
+ route %r{features/[^/]*/boolean/?\Z}
10
10
 
11
11
  def post
12
12
  feature_name = Rack::Utils.unescape(path_parts[-2])
@@ -0,0 +1,21 @@
1
+ require 'flipper/api/action'
2
+ require 'flipper/api/v1/decorators/feature'
3
+
4
+ module Flipper
5
+ module Api
6
+ module V1
7
+ module Actions
8
+ class ClearFeature < Api::Action
9
+ route %r{features/[^/]*/clear/?\Z}
10
+
11
+ def delete
12
+ feature_name = Rack::Utils.unescape(path_parts[-2])
13
+ feature = flipper[feature_name]
14
+ flipper.adapter.clear(feature)
15
+ json_response({}, 204)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -6,25 +6,17 @@ module Flipper
6
6
  module V1
7
7
  module Actions
8
8
  class Feature < Api::Action
9
-
10
- route %r{api/v1/features/[^/]*/?\Z}
9
+ route %r{features/[^/]*/?\Z}
11
10
 
12
11
  def get
13
- if feature_names.include?(feature_name)
14
- feature = Decorators::Feature.new(flipper[feature_name])
15
- json_response(feature.as_json)
16
- else
17
- json_error_response(:feature_not_found)
18
- end
12
+ return json_error_response(:feature_not_found) unless feature_exists?(feature_name)
13
+ feature = Decorators::Feature.new(flipper[feature_name])
14
+ json_response(feature.as_json)
19
15
  end
20
16
 
21
17
  def delete
22
- if feature_names.include?(feature_name)
23
- flipper.remove(feature_name)
24
- json_response({}, 204)
25
- else
26
- json_error_response(:feature_not_found)
27
- end
18
+ flipper.remove(feature_name)
19
+ json_response({}, 204)
28
20
  end
29
21
 
30
22
  private
@@ -33,8 +25,8 @@ module Flipper
33
25
  @feature_name ||= Rack::Utils.unescape(path_parts.last)
34
26
  end
35
27
 
36
- def feature_names
37
- @feature_names ||= flipper.adapter.features
28
+ def feature_exists?(feature_name)
29
+ flipper.features.map(&:key).include?(feature_name)
38
30
  end
39
31
  end
40
32
  end
@@ -1,23 +1,35 @@
1
1
  require 'flipper/api/action'
2
2
  require 'flipper/api/v1/decorators/feature'
3
- require 'json'
4
3
 
5
4
  module Flipper
6
5
  module Api
7
6
  module V1
8
7
  module Actions
9
8
  class Features < Api::Action
10
-
11
- route %r{api/v1/features\Z}
9
+ route(/features\Z/)
12
10
 
13
11
  def get
14
- features = flipper.features.map { |feature|
12
+ keys = params['keys']
13
+ features = if keys
14
+ names = keys.split(',')
15
+ if names.empty?
16
+ []
17
+ else
18
+ existing_feature_names = names.keep_if do |feature_name|
19
+ feature_exists?(feature_name)
20
+ end
21
+
22
+ flipper.preload(existing_feature_names)
23
+ end
24
+ else
25
+ flipper.features
26
+ end
27
+
28
+ decorated_features = features.map do |feature|
15
29
  Decorators::Feature.new(feature).as_json
16
- }
30
+ end
17
31
 
18
- json_response({
19
- features: features
20
- })
32
+ json_response(features: decorated_features)
21
33
  end
22
34
 
23
35
  def post
@@ -27,6 +39,12 @@ module Flipper
27
39
  decorated_feature = Decorators::Feature.new(feature)
28
40
  json_response(decorated_feature.as_json, 200)
29
41
  end
42
+
43
+ private
44
+
45
+ def feature_exists?(feature_name)
46
+ flipper.features.map(&:key).include?(feature_name)
47
+ end
30
48
  end
31
49
  end
32
50
  end
@@ -6,7 +6,7 @@ module Flipper
6
6
  module V1
7
7
  module Actions
8
8
  class GroupsGate < Api::Action
9
- route %r{api/v1/features/[^/]*/groups/?\Z}
9
+ route %r{features/[^/]*/groups/?\Z}
10
10
 
11
11
  def post
12
12
  ensure_valid_params
@@ -27,8 +27,23 @@ module Flipper
27
27
  private
28
28
 
29
29
  def ensure_valid_params
30
- json_error_response(:feature_not_found) unless feature_names.include?(feature_name)
31
- json_error_response(:group_not_registered) unless Flipper.group_exists?(group_name)
30
+ if group_name.nil? || group_name.empty?
31
+ json_error_response(:name_invalid)
32
+ end
33
+
34
+ return if allow_unregistered_groups?
35
+ return if Flipper.group_exists?(group_name)
36
+
37
+ json_error_response(:group_not_registered)
38
+ end
39
+
40
+ def allow_unregistered_groups?
41
+ allow_unregistered_groups = params['allow_unregistered_groups']
42
+ allow_unregistered_groups && allow_unregistered_groups == 'true'
43
+ end
44
+
45
+ def disallow_unregistered_groups?
46
+ !allow_unregistered_groups?
32
47
  end
33
48
 
34
49
  def feature_name
@@ -38,10 +53,6 @@ module Flipper
38
53
  def group_name
39
54
  @group_name ||= params['name']
40
55
  end
41
-
42
- def feature_names
43
- @feature_names ||= flipper.adapter.features
44
- end
45
56
  end
46
57
  end
47
58
  end
@@ -6,10 +6,13 @@ module Flipper
6
6
  module V1
7
7
  module Actions
8
8
  class PercentageOfActorsGate < Api::Action
9
- route %r{api/v1/features/[^/]*/percentage_of_actors/?\Z}
9
+ route %r{features/[^/]*/percentage_of_actors/?\Z}
10
10
 
11
11
  def post
12
- ensure_valid_enable_params
12
+ if percentage < 0 || percentage > 100
13
+ json_error_response(:percentage_invalid)
14
+ end
15
+
13
16
  feature = flipper[feature_name]
14
17
  feature.enable_percentage_of_actors(percentage)
15
18
  decorated_feature = Decorators::Feature.new(feature)
@@ -17,7 +20,6 @@ module Flipper
17
20
  end
18
21
 
19
22
  def delete
20
- ensure_valid_disable_params
21
23
  feature = flipper[feature_name]
22
24
  feature.disable_percentage_of_actors
23
25
  decorated_feature = Decorators::Feature.new(feature)
@@ -26,22 +28,6 @@ module Flipper
26
28
 
27
29
  private
28
30
 
29
- def ensure_valid_enable_params
30
- unless feature_names.include?(feature_name)
31
- json_error_response(:feature_not_found)
32
- end
33
-
34
- if percentage < 0 || percentage > 100
35
- json_error_response(:percentage_invalid)
36
- end
37
- end
38
-
39
- def ensure_valid_disable_params
40
- unless feature_names.include?(feature_name)
41
- json_error_response(:feature_not_found)
42
- end
43
- end
44
-
45
31
  def feature_name
46
32
  @feature_name ||= Rack::Utils.unescape(path_parts[-2])
47
33
  end
@@ -53,12 +39,8 @@ module Flipper
53
39
  -1
54
40
  end
55
41
  end
56
-
57
- def feature_names
58
- @feature_names ||= flipper.adapter.features
59
- end
60
- end
61
42
  end
62
43
  end
63
44
  end
64
45
  end
46
+ end
@@ -6,10 +6,13 @@ module Flipper
6
6
  module V1
7
7
  module Actions
8
8
  class PercentageOfTimeGate < Api::Action
9
- route %r{api/v1/features/[^/]*/percentage_of_time/?\Z}
9
+ route %r{features/[^/]*/percentage_of_time/?\Z}
10
10
 
11
11
  def post
12
- ensure_valid_enable_params
12
+ if percentage < 0 || percentage > 100
13
+ json_error_response(:percentage_invalid)
14
+ end
15
+
13
16
  feature = flipper[feature_name]
14
17
  feature.enable_percentage_of_time(percentage)
15
18
  decorated_feature = Decorators::Feature.new(feature)
@@ -17,31 +20,15 @@ module Flipper
17
20
  end
18
21
 
19
22
  def delete
20
- ensure_valid_disable_params
21
23
  feature = flipper[feature_name]
22
24
  feature.disable_percentage_of_time
25
+
23
26
  decorated_feature = Decorators::Feature.new(feature)
24
27
  json_response(decorated_feature.as_json, 200)
25
28
  end
26
29
 
27
30
  private
28
31
 
29
- def ensure_valid_enable_params
30
- unless feature_names.include?(feature_name)
31
- json_error_response(:feature_not_found)
32
- end
33
-
34
- if percentage < 0 || percentage > 100
35
- json_error_response(:percentage_invalid)
36
- end
37
- end
38
-
39
- def ensure_valid_disable_params
40
- unless feature_names.include?(feature_name)
41
- json_error_response(:feature_not_found)
42
- end
43
- end
44
-
45
32
  def feature_name
46
33
  @feature_name ||= Rack::Utils.unescape(path_parts[-2])
47
34
  end
@@ -53,10 +40,6 @@ module Flipper
53
40
  -1
54
41
  end
55
42
  end
56
-
57
- def feature_names
58
- @feature_names ||= flipper.adapter.features
59
- end
60
43
  end
61
44
  end
62
45
  end
@@ -6,19 +6,18 @@ module Flipper
6
6
  module V1
7
7
  module Decorators
8
8
  class Feature < SimpleDelegator
9
-
10
9
  # Public: The feature being decorated.
11
10
  alias_method :feature, :__getobj__
12
11
 
13
12
  # Public: Returns instance as hash that is ready to be json dumped.
14
13
  def as_json
15
- gate_values = feature.gate_values
14
+ gate_values = feature.adapter.get(self)
16
15
  {
17
16
  'key' => key,
18
17
  'state' => state.to_s,
19
- 'gates' => gates.map { |gate|
18
+ 'gates' => gates.map do |gate|
20
19
  Decorators::Gate.new(gate, gate_values[gate.key]).as_json
21
- },
20
+ end,
22
21
  }
23
22
  end
24
23
  end
data/lib/flipper/api.rb CHANGED
@@ -1,43 +1,27 @@
1
1
  require 'rack'
2
2
  require 'flipper'
3
+ require 'flipper/middleware/setup_env'
4
+ require 'flipper/middleware/memoizer'
3
5
  require 'flipper/api/middleware'
6
+ require 'flipper/api/json_params'
4
7
  require 'flipper/api/actor'
5
8
 
6
9
  module Flipper
7
10
  module Api
8
11
  CONTENT_TYPE = 'application/json'.freeze
9
12
 
10
- def self.app(flipper)
11
- app = App.new(200,{ 'Content-Type' => CONTENT_TYPE }, [''])
13
+ def self.app(flipper = nil)
14
+ app = ->(_) { [404, { 'Content-Type'.freeze => CONTENT_TYPE }, ['{}'.freeze]] }
12
15
  builder = Rack::Builder.new
13
16
  yield builder if block_given?
14
- builder.use Flipper::Api::Middleware, flipper
17
+ builder.use Flipper::Middleware::SetupEnv, flipper
18
+ builder.use Flipper::Middleware::Memoizer
19
+ builder.use Flipper::Api::JsonParams
20
+ builder.use Flipper::Api::Middleware
15
21
  builder.run app
22
+ klass = self
23
+ builder.define_singleton_method(:inspect) { klass.inspect } # pretty rake routes output
16
24
  builder
17
25
  end
18
-
19
- class App
20
- # Public: HTTP response code
21
- # Use this method to update status code before responding
22
- attr_writer :status
23
-
24
- def initialize(status, headers, body)
25
- @status = status
26
- @headers = headers
27
- @body = body
28
- end
29
-
30
- # Public : Rack expects object that responds to call
31
- # env - environment hash
32
- def call(env)
33
- response
34
- end
35
-
36
- private
37
-
38
- def response
39
- [@status, @headers, @body]
40
- end
41
- end
42
26
  end
43
27
  end
@@ -1,3 +1,3 @@
1
1
  module Flipper
2
- VERSION = "0.10.2".freeze
2
+ VERSION = '0.11.0.beta1'.freeze
3
3
  end