cp-sparrow 0.0.11

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 (77) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +23 -0
  3. data/.ruby-gemset +1 -0
  4. data/.ruby-version +1 -0
  5. data/Gemfile +6 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +66 -0
  8. data/Rakefile +32 -0
  9. data/lib/sparrow.rb +25 -0
  10. data/lib/sparrow/configuration.rb +36 -0
  11. data/lib/sparrow/core_ext/hash.rb +21 -0
  12. data/lib/sparrow/middleware.rb +99 -0
  13. data/lib/sparrow/path_normalizer.rb +10 -0
  14. data/lib/sparrow/railtie.rb +11 -0
  15. data/lib/sparrow/request_middleware.rb +11 -0
  16. data/lib/sparrow/response_middleware.rb +37 -0
  17. data/lib/sparrow/route_parser.rb +32 -0
  18. data/lib/sparrow/strategies/form_hash.rb +42 -0
  19. data/lib/sparrow/strategies/ignore.rb +42 -0
  20. data/lib/sparrow/strategies/json_format_strategies/array_strategy.rb +17 -0
  21. data/lib/sparrow/strategies/json_format_strategies/default_json_format_strategy.rb +17 -0
  22. data/lib/sparrow/strategies/json_format_strategies/json_format_strategy.rb +35 -0
  23. data/lib/sparrow/strategies/json_format_strategies/rack_body.rb +17 -0
  24. data/lib/sparrow/strategies/key_transformation/camelize_key.rb +27 -0
  25. data/lib/sparrow/strategies/key_transformation/key_normalizer.rb +9 -0
  26. data/lib/sparrow/strategies/key_transformation/underscore_key.rb +13 -0
  27. data/lib/sparrow/strategies/raw_input.rb +48 -0
  28. data/lib/sparrow/strategies/transform_params.rb +38 -0
  29. data/lib/sparrow/transformable.rb +76 -0
  30. data/lib/sparrow/version.rb +3 -0
  31. data/sparrow.gemspec +35 -0
  32. data/spec/integration/apps/rack_app/app.rb +28 -0
  33. data/spec/integration/apps/rack_app/config.ru +12 -0
  34. data/spec/integration/apps/rails_app/README.rdoc +261 -0
  35. data/spec/integration/apps/rails_app/Rakefile +7 -0
  36. data/spec/integration/apps/rails_app/app/assets/javascripts/application.js +15 -0
  37. data/spec/integration/apps/rails_app/app/assets/stylesheets/application.css +13 -0
  38. data/spec/integration/apps/rails_app/app/controllers/application_controller.rb +3 -0
  39. data/spec/integration/apps/rails_app/app/controllers/welcome_controller.rb +50 -0
  40. data/spec/integration/apps/rails_app/app/helpers/application_helper.rb +2 -0
  41. data/spec/integration/apps/rails_app/app/mailers/.gitkeep +0 -0
  42. data/spec/integration/apps/rails_app/app/models/.gitkeep +0 -0
  43. data/spec/integration/apps/rails_app/app/views/layouts/application.html.erb +14 -0
  44. data/spec/integration/apps/rails_app/config.ru +4 -0
  45. data/spec/integration/apps/rails_app/config/application.rb +72 -0
  46. data/spec/integration/apps/rails_app/config/boot.rb +10 -0
  47. data/spec/integration/apps/rails_app/config/environment.rb +5 -0
  48. data/spec/integration/apps/rails_app/config/environments/development.rb +31 -0
  49. data/spec/integration/apps/rails_app/config/environments/production.rb +64 -0
  50. data/spec/integration/apps/rails_app/config/environments/test.rb +32 -0
  51. data/spec/integration/apps/rails_app/config/initializers/backtrace_silencers.rb +7 -0
  52. data/spec/integration/apps/rails_app/config/initializers/inflections.rb +15 -0
  53. data/spec/integration/apps/rails_app/config/initializers/mime_types.rb +5 -0
  54. data/spec/integration/apps/rails_app/config/initializers/secret_token.rb +7 -0
  55. data/spec/integration/apps/rails_app/config/initializers/session_store.rb +8 -0
  56. data/spec/integration/apps/rails_app/config/initializers/wrap_parameters.rb +10 -0
  57. data/spec/integration/apps/rails_app/config/locales/en.yml +5 -0
  58. data/spec/integration/apps/rails_app/config/routes.rb +64 -0
  59. data/spec/integration/apps/rails_app/lib/assets/.gitkeep +0 -0
  60. data/spec/integration/apps/rails_app/public/404.html +26 -0
  61. data/spec/integration/apps/rails_app/public/422.html +26 -0
  62. data/spec/integration/apps/rails_app/public/500.html +25 -0
  63. data/spec/integration/apps/rails_app/public/favicon.ico +0 -0
  64. data/spec/integration/apps/rails_app/script/rails +6 -0
  65. data/spec/integration/rack/camel_caser_spec.rb +49 -0
  66. data/spec/integration/rails/camel_caser_accept_header_spec.rb +55 -0
  67. data/spec/integration/rails/camel_caser_spec.rb +207 -0
  68. data/spec/spec_helper.rb +12 -0
  69. data/spec/support/rack_app_helper.rb +19 -0
  70. data/spec/support/rails_app_helper.rb +21 -0
  71. data/spec/support/unit_spec_helper.rb +5 -0
  72. data/spec/unit/camel_caser_spec.rb +23 -0
  73. data/spec/unit/camelize_key_spec.rb +19 -0
  74. data/spec/unit/configuration_spec.rb +47 -0
  75. data/spec/unit/path_normalizer_spec.rb +23 -0
  76. data/spec/unit/route_parser_spec.rb +45 -0
  77. metadata +295 -0
@@ -0,0 +1,42 @@
1
+ require 'active_support/core_ext/object/blank'
2
+ require 'sparrow/transformable'
3
+
4
+ module Sparrow
5
+ module Strategies
6
+ class FormHash
7
+ REQUEST_FORM_HASH_KEY = 'rack.request.form_hash'
8
+ include Transformable
9
+
10
+ attr_reader :env, :type
11
+
12
+ def self.handle(env, type)
13
+ self.new(env, type).handle
14
+ end
15
+
16
+ def initialize(env, type = :request, params = nil)
17
+ @env = env
18
+ @params = params
19
+ @type = type
20
+ end
21
+
22
+ def handle
23
+ super
24
+ handle_form_hash
25
+ end
26
+
27
+ def params
28
+ @params || env[REQUEST_FORM_HASH_KEY]
29
+ end
30
+
31
+ private
32
+
33
+ def handle_form_hash
34
+ if params.present?
35
+ transformed_params = transform_params
36
+ @env[REQUEST_FORM_HASH_KEY] = transformed_params
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+
@@ -0,0 +1,42 @@
1
+ module Sparrow
2
+ module Strategies
3
+ class Ignore
4
+ include Transformable
5
+
6
+ def initialize(env, type = :request, params = nil)
7
+ @env = env
8
+ @params = params
9
+ @type = type
10
+ end
11
+
12
+ def params
13
+ ret = @params || @env['rack.input'].send(:read)
14
+ @env['rack.input'].rewind
15
+ ret
16
+ end
17
+
18
+ def self.handle(env, type)
19
+ new(env, type).handle
20
+ end
21
+
22
+ def handle
23
+ # synchronize rack.input and form hash values
24
+ input = @env['rack.input'].gets
25
+
26
+ begin
27
+ @env['rack.request.form_hash'] = MultiJson.load(input)
28
+ rescue MultiJson::ParseError
29
+ # ignore
30
+ ensure
31
+ @env['rack.input'].rewind
32
+ end if input.present?
33
+
34
+ @env
35
+ end
36
+
37
+ def transform_params
38
+ ensure_json
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,17 @@
1
+ require 'sparrow/strategies/json_format_strategies/json_format_strategy'
2
+
3
+ module Sparrow
4
+ module Strategies
5
+ class ArrayStrategy < JsonFormatStrategy
6
+ register_json_format
7
+
8
+ def match?(input)
9
+ input.is_a? Array
10
+ end
11
+
12
+ def convert(input)
13
+ input.first
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ require 'singleton'
2
+
3
+ module Sparrow
4
+ module Strategies
5
+ class DefaultJsonFormatStrategy
6
+ include Singleton
7
+
8
+ def match?(input)
9
+ true
10
+ end
11
+
12
+ def convert(input)
13
+ input.to_s
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,35 @@
1
+ require 'sparrow/strategies/json_format_strategies/default_json_format_strategy'
2
+ require 'active_support/core_ext/object/blank'
3
+
4
+ module Sparrow
5
+ module Strategies
6
+ class JsonFormatStrategy
7
+ def initialize(*args)
8
+
9
+ end
10
+
11
+ def self.register_json_format(*args)
12
+ init(args)
13
+ @@json_format_strategies << self.new(args)
14
+ end
15
+
16
+ def self.convert(body)
17
+ strategy = json_format_strategies.select do |strategy|
18
+ strategy.match?(body)
19
+ end.first
20
+ strategy.convert(body)
21
+ end
22
+
23
+ private
24
+ def self.init(*args)
25
+ @@json_format_strategies ||= Array.new(args)
26
+ end
27
+
28
+ def self.json_format_strategies
29
+ init
30
+ default = Sparrow::Strategies::DefaultJsonFormatStrategy.instance
31
+ @@json_format_strategies.reject(&:blank?) + [default]
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,17 @@
1
+ require File.dirname(__FILE__) + '/json_format_strategy'
2
+
3
+ module Sparrow
4
+ module Strategies
5
+ class RackBody < JsonFormatStrategy
6
+ register_json_format
7
+
8
+ def match?(input)
9
+ input.respond_to?(:body)
10
+ end
11
+
12
+ def convert(input)
13
+ input.body
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,27 @@
1
+ require File.dirname(__FILE__) + '/key_normalizer'
2
+
3
+ module Sparrow
4
+ module Strategies
5
+ class CamelizeKey
6
+ include KeyNormalizer
7
+
8
+ attr_accessor :strategy
9
+
10
+ def initialize(strategy = :lower)
11
+ self.strategy = strategy
12
+ end
13
+
14
+ def transform_key(key)
15
+ # dont touch all_Upper Keys (like "DE")
16
+ # unless configuration.default_ignore_all_uppercase_keys
17
+ # is set to false
18
+ if Sparrow.configuration.camelize_ignore_uppercase_keys &&
19
+ key.upcase == key
20
+ normalize_key(key)
21
+ else
22
+ normalize_key(key).camelize(strategy)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,9 @@
1
+ module Sparrow
2
+ module Strategies
3
+ module KeyNormalizer
4
+ def normalize_key(key)
5
+ key.to_s
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,13 @@
1
+ require File.dirname(__FILE__) + '/key_normalizer'
2
+
3
+ module Sparrow
4
+ module Strategies
5
+ class UnderscoreKey
6
+ include KeyNormalizer
7
+
8
+ def transform_key(key)
9
+ normalize_key(key).underscore
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,48 @@
1
+ require 'active_support/core_ext/object/blank'
2
+
3
+ module Sparrow
4
+ module Strategies
5
+ class RawInput
6
+ include Transformable
7
+
8
+ attr_reader :env, :type
9
+
10
+ def self.handle(env, type)
11
+ self.new(env, type).handle
12
+ end
13
+
14
+ def initialize(env, type = :request, params = nil)
15
+ @env = env || {}
16
+ @params = params
17
+ @type = type
18
+ end
19
+
20
+ def handle
21
+ super
22
+ handle_raw_rack
23
+ end
24
+
25
+ def params
26
+ if @params
27
+ @params
28
+ else
29
+ input_io = @env['rack.input']
30
+ params = input_io.send(:read)
31
+ input_io.rewind
32
+ params
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def handle_raw_rack
39
+ if params.present?
40
+ new_raw_input = json_body.force_encoding("BINARY")
41
+ @env['rack.input'] = StringIO.new(new_raw_input)
42
+ @env['rack.input'].rewind
43
+ @env['CONTENT_LENGTH'] = new_raw_input.length
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,38 @@
1
+ require 'active_support/core_ext/string'
2
+ if ActiveSupport::VERSION::STRING.match(/3\.\d+\.\d+/)
3
+ require 'sparrow/core_ext/hash'
4
+ end
5
+
6
+ require 'sparrow/strategies/key_transformation/underscore_key'
7
+ require 'sparrow/strategies/key_transformation/camelize_key'
8
+
9
+ module Sparrow
10
+ module Strategies
11
+ class TransformParams
12
+ attr_accessor :key_transformation_strategy
13
+
14
+ def initialize(key_transformation_strategy_buzzword)
15
+ key_transformation_strategy = create_key_transformation_strategy(
16
+ key_transformation_strategy_buzzword)
17
+ self.key_transformation_strategy = key_transformation_strategy
18
+ end
19
+
20
+ def transform(collection_or_hash)
21
+ case collection_or_hash
22
+ when Array
23
+ collection_or_hash.map { |element| transform(element) }
24
+ when Hash
25
+ collection_or_hash.deep_transform_keys do |key|
26
+ key_transformation_strategy.transform_key(key)
27
+ end
28
+ end
29
+ end
30
+
31
+ def create_key_transformation_strategy(key_transformation_strategy_buzzword)
32
+ class_name = "#{key_transformation_strategy_buzzword.to_s}_key".camelize
33
+ strategy_class = "Sparrow::Strategies::#{class_name}".constantize
34
+ strategy_class.new
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,76 @@
1
+ require 'sparrow/strategies/transform_params'
2
+ require 'sparrow/strategies/json_format_strategies/json_format_strategy'
3
+
4
+ if ActiveSupport::VERSION::STRING.match(/3\.\d+\.\d+/)
5
+ require 'active_support/core_ext/object/to_param'
6
+ require 'active_support/core_ext/object/to_query'
7
+ end
8
+
9
+ module Sparrow
10
+ module Transformable
11
+ def transform_params
12
+ transform_params_strategy.transform(ensure_json)
13
+ end
14
+
15
+ def transform_strategy
16
+ default =
17
+ Sparrow.configuration.default_json_key_transformation_strategy(type)
18
+ strategy = json_format || default
19
+ strategy.to_sym
20
+ end
21
+
22
+ def handle
23
+ transform_query_string
24
+ end
25
+
26
+ def json_body
27
+ json = parsable_json_string(transform_params)
28
+ MultiJson.load(json)
29
+ json
30
+ rescue MultiJson::ParseError
31
+ MultiJson.dump(ensure_json)
32
+ end
33
+
34
+ private
35
+ def json_format
36
+ if respond_to?(:env) then
37
+ env[Sparrow.configuration.json_format_header(type)]
38
+ else
39
+ nil
40
+ end
41
+ end
42
+
43
+ def ensure_json
44
+ json_params = if !params.is_a?(Hash)
45
+ Sparrow::Strategies::JsonFormatStrategy.convert(params)
46
+ elsif params.is_a?(Hash) && params.values == [nil] &&
47
+ params.keys.length == 1
48
+ params.keys.first
49
+ else
50
+ params
51
+ end
52
+ return MultiJson.load(json_params) if json_params.is_a?(String)
53
+ json_params
54
+ end
55
+
56
+ def parsable_json_string(transformable_params)
57
+ if [Hash, Array].include? transformable_params.class
58
+ MultiJson.dump(transformable_params)
59
+ else
60
+ transformable_params
61
+ end
62
+ end
63
+
64
+ def transform_params_strategy
65
+ transform_params = Sparrow::Strategies::TransformParams
66
+ transform_params.new(transform_strategy)
67
+ end
68
+
69
+ def transform_query_string
70
+ env_query_hash = Rack::Utils.parse_nested_query(env['QUERY_STRING'])
71
+ transformed_hash = transform_params_strategy.transform(env_query_hash)
72
+ env['QUERY_STRING'] = transformed_hash.to_param
73
+ end
74
+
75
+ end
76
+ end
@@ -0,0 +1,3 @@
1
+ module Sparrow
2
+ VERSION = '0.0.11'
3
+ end
@@ -0,0 +1,35 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ rails_version = ENV["RAILS_VERSION"] || "3.2.21"
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'sparrow/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = "cp-sparrow"
9
+ spec.version = Sparrow::VERSION
10
+ spec.authors = ["Daniel Schmidt", "Andreas Müller"]
11
+ spec.email = ["dsci@code79.net", "anmuel86@gmail.com"]
12
+ spec.summary = %q{A POC to have a Rack middleware parsing the params keys into underscore}
13
+ spec.description = %q{
14
+ A collection of 2 middlewares to convert json formats to other formats
15
+ such as camelCase and snake_case. Both converting responses and requests are
16
+ supported.
17
+ }
18
+ spec.homepage = ""
19
+ spec.license = "MIT"
20
+
21
+ spec.files = `git ls-files -z`.split("\x0")
22
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
23
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
24
+ spec.require_paths = ["lib"]
25
+
26
+ spec.add_runtime_dependency "activesupport", ">= 3.2.17"
27
+ spec.add_development_dependency "pry"
28
+ spec.add_development_dependency "bundler", "~> 1.5"
29
+ spec.add_development_dependency "rake"
30
+ spec.add_development_dependency "rspec", '~> 3'
31
+ spec.add_development_dependency "rspec-its"
32
+ spec.add_development_dependency "rack-test"
33
+ spec.add_development_dependency "multi_json"
34
+ spec.add_development_dependency "rails", rails_version
35
+ end
@@ -0,0 +1,28 @@
1
+ class App
2
+
3
+ def call(env)
4
+ params = env["rack.input"].gets
5
+ response = Rack::Response.new
6
+ response['Content-Type'] = 'application/json'
7
+ response.write(json_response(params))
8
+ response.finish
9
+ end
10
+
11
+ private
12
+
13
+ def json_response(params)
14
+ hsh_params = MultiJson.load(params)
15
+ keys = hsh_params.reduce([]) do |result, (key, value)|
16
+ result << key
17
+ if value.is_a?(Hash)
18
+ result << value.keys
19
+ end
20
+ result
21
+ end.flatten
22
+ MultiJson.dump({
23
+ keys: keys,
24
+ fakeKey: true,
25
+ fake_key: false
26
+ })
27
+ end
28
+ end