flipper-api 0.10.2 → 0.11.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
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