cp-sparrow 0.0.11

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