grape 1.2.5 → 1.4.0

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 (262) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +97 -0
  3. data/LICENSE +1 -1
  4. data/README.md +53 -16
  5. data/UPGRADING.md +231 -23
  6. data/grape.gemspec +10 -1
  7. data/lib/grape.rb +6 -7
  8. data/lib/grape/api.rb +4 -2
  9. data/lib/grape/api/helpers.rb +2 -0
  10. data/lib/grape/api/instance.rb +36 -33
  11. data/lib/grape/config.rb +2 -0
  12. data/lib/grape/content_types.rb +34 -0
  13. data/lib/grape/cookies.rb +2 -0
  14. data/lib/grape/dsl/api.rb +2 -0
  15. data/lib/grape/dsl/callbacks.rb +2 -0
  16. data/lib/grape/dsl/configuration.rb +2 -0
  17. data/lib/grape/dsl/desc.rb +2 -0
  18. data/lib/grape/dsl/headers.rb +2 -0
  19. data/lib/grape/dsl/helpers.rb +4 -2
  20. data/lib/grape/dsl/inside_route.rb +83 -34
  21. data/lib/grape/dsl/logger.rb +2 -0
  22. data/lib/grape/dsl/middleware.rb +2 -0
  23. data/lib/grape/dsl/parameters.rb +8 -6
  24. data/lib/grape/dsl/request_response.rb +4 -2
  25. data/lib/grape/dsl/routing.rb +9 -5
  26. data/lib/grape/dsl/settings.rb +7 -1
  27. data/lib/grape/dsl/validations.rb +20 -1
  28. data/lib/grape/eager_load.rb +3 -1
  29. data/lib/grape/endpoint.rb +21 -13
  30. data/lib/grape/error_formatter.rb +3 -1
  31. data/lib/grape/error_formatter/base.rb +2 -0
  32. data/lib/grape/error_formatter/json.rb +2 -0
  33. data/lib/grape/error_formatter/txt.rb +2 -0
  34. data/lib/grape/error_formatter/xml.rb +2 -0
  35. data/lib/grape/exceptions/base.rb +11 -13
  36. data/lib/grape/exceptions/incompatible_option_values.rb +2 -0
  37. data/lib/grape/exceptions/invalid_accept_header.rb +2 -0
  38. data/lib/grape/exceptions/invalid_formatter.rb +2 -0
  39. data/lib/grape/exceptions/invalid_message_body.rb +2 -0
  40. data/lib/grape/exceptions/invalid_response.rb +2 -0
  41. data/lib/grape/exceptions/invalid_version_header.rb +2 -0
  42. data/lib/grape/exceptions/invalid_versioner_option.rb +2 -0
  43. data/lib/grape/exceptions/invalid_with_option_for_represent.rb +2 -0
  44. data/lib/grape/exceptions/method_not_allowed.rb +2 -0
  45. data/lib/grape/exceptions/missing_group_type.rb +2 -0
  46. data/lib/grape/exceptions/missing_mime_type.rb +2 -0
  47. data/lib/grape/exceptions/missing_option.rb +2 -0
  48. data/lib/grape/exceptions/missing_vendor_option.rb +2 -0
  49. data/lib/grape/exceptions/unknown_options.rb +2 -0
  50. data/lib/grape/exceptions/unknown_parameter.rb +2 -0
  51. data/lib/grape/exceptions/unknown_validator.rb +2 -0
  52. data/lib/grape/exceptions/unsupported_group_type.rb +2 -0
  53. data/lib/grape/exceptions/validation.rb +3 -1
  54. data/lib/grape/exceptions/validation_array_errors.rb +2 -0
  55. data/lib/grape/exceptions/validation_errors.rb +13 -12
  56. data/lib/grape/extensions/active_support/hash_with_indifferent_access.rb +4 -3
  57. data/lib/grape/extensions/deep_mergeable_hash.rb +2 -0
  58. data/lib/grape/extensions/deep_symbolize_hash.rb +2 -0
  59. data/lib/grape/extensions/hash.rb +2 -0
  60. data/lib/grape/extensions/hashie/mash.rb +2 -0
  61. data/lib/grape/formatter.rb +5 -3
  62. data/lib/grape/formatter/json.rb +2 -0
  63. data/lib/grape/formatter/serializable_hash.rb +2 -0
  64. data/lib/grape/formatter/txt.rb +2 -0
  65. data/lib/grape/formatter/xml.rb +2 -0
  66. data/lib/grape/http/headers.rb +50 -18
  67. data/lib/grape/middleware/auth/base.rb +2 -0
  68. data/lib/grape/middleware/auth/dsl.rb +2 -0
  69. data/lib/grape/middleware/auth/strategies.rb +2 -0
  70. data/lib/grape/middleware/auth/strategy_info.rb +2 -0
  71. data/lib/grape/middleware/base.rb +7 -7
  72. data/lib/grape/middleware/error.rb +3 -1
  73. data/lib/grape/middleware/filter.rb +2 -0
  74. data/lib/grape/middleware/formatter.rb +8 -6
  75. data/lib/grape/middleware/globals.rb +2 -0
  76. data/lib/grape/middleware/helpers.rb +2 -0
  77. data/lib/grape/middleware/stack.rb +4 -1
  78. data/lib/grape/middleware/versioner.rb +2 -0
  79. data/lib/grape/middleware/versioner/accept_version_header.rb +2 -0
  80. data/lib/grape/middleware/versioner/header.rb +6 -4
  81. data/lib/grape/middleware/versioner/param.rb +3 -1
  82. data/lib/grape/middleware/versioner/parse_media_type_patch.rb +4 -1
  83. data/lib/grape/middleware/versioner/path.rb +3 -1
  84. data/lib/grape/namespace.rb +14 -2
  85. data/lib/grape/parser.rb +3 -1
  86. data/lib/grape/parser/json.rb +2 -0
  87. data/lib/grape/parser/xml.rb +2 -0
  88. data/lib/grape/path.rb +15 -3
  89. data/lib/grape/presenters/presenter.rb +2 -0
  90. data/lib/grape/request.rb +15 -8
  91. data/lib/grape/router.rb +30 -29
  92. data/lib/grape/router/attribute_translator.rb +39 -8
  93. data/lib/grape/router/pattern.rb +20 -16
  94. data/lib/grape/router/route.rb +12 -26
  95. data/lib/grape/{serve_file → serve_stream}/file_body.rb +3 -1
  96. data/lib/grape/{serve_file → serve_stream}/sendfile_response.rb +3 -1
  97. data/lib/grape/{serve_file/file_response.rb → serve_stream/stream_response.rb} +10 -8
  98. data/lib/grape/util/base_inheritable.rb +15 -6
  99. data/lib/grape/util/cache.rb +20 -0
  100. data/lib/grape/util/endpoint_configuration.rb +2 -0
  101. data/lib/grape/util/env.rb +19 -17
  102. data/lib/grape/util/inheritable_setting.rb +2 -0
  103. data/lib/grape/util/inheritable_values.rb +2 -0
  104. data/lib/grape/util/json.rb +2 -0
  105. data/lib/grape/util/lazy_block.rb +2 -0
  106. data/lib/grape/util/lazy_object.rb +43 -0
  107. data/lib/grape/util/lazy_value.rb +2 -0
  108. data/lib/grape/util/registrable.rb +2 -0
  109. data/lib/grape/util/reverse_stackable_values.rb +4 -0
  110. data/lib/grape/util/stackable_values.rb +10 -20
  111. data/lib/grape/util/strict_hash_configuration.rb +2 -0
  112. data/lib/grape/util/xml.rb +2 -0
  113. data/lib/grape/validations.rb +2 -0
  114. data/lib/grape/validations/attributes_iterator.rb +3 -3
  115. data/lib/grape/validations/multiple_attributes_iterator.rb +2 -0
  116. data/lib/grape/validations/params_scope.rb +27 -14
  117. data/lib/grape/validations/single_attribute_iterator.rb +13 -2
  118. data/lib/grape/validations/types.rb +12 -34
  119. data/lib/grape/validations/types/array_coercer.rb +65 -0
  120. data/lib/grape/validations/types/build_coercer.rb +47 -49
  121. data/lib/grape/validations/types/custom_type_coercer.rb +15 -49
  122. data/lib/grape/validations/types/custom_type_collection_coercer.rb +10 -25
  123. data/lib/grape/validations/types/dry_type_coercer.rb +76 -0
  124. data/lib/grape/validations/types/file.rb +22 -18
  125. data/lib/grape/validations/types/json.rb +46 -39
  126. data/lib/grape/validations/types/multiple_type_coercer.rb +14 -33
  127. data/lib/grape/validations/types/primitive_coercer.rb +67 -0
  128. data/lib/grape/validations/types/set_coercer.rb +40 -0
  129. data/lib/grape/validations/types/variant_collection_coercer.rb +5 -13
  130. data/lib/grape/validations/validator_factory.rb +2 -0
  131. data/lib/grape/validations/validators/all_or_none.rb +3 -1
  132. data/lib/grape/validations/validators/allow_blank.rb +3 -1
  133. data/lib/grape/validations/validators/as.rb +2 -0
  134. data/lib/grape/validations/validators/at_least_one_of.rb +3 -1
  135. data/lib/grape/validations/validators/base.rb +8 -5
  136. data/lib/grape/validations/validators/coerce.rb +39 -29
  137. data/lib/grape/validations/validators/default.rb +2 -1
  138. data/lib/grape/validations/validators/exactly_one_of.rb +6 -2
  139. data/lib/grape/validations/validators/except_values.rb +3 -1
  140. data/lib/grape/validations/validators/multiple_params_base.rb +2 -0
  141. data/lib/grape/validations/validators/mutual_exclusion.rb +3 -1
  142. data/lib/grape/validations/validators/presence.rb +3 -1
  143. data/lib/grape/validations/validators/regexp.rb +4 -2
  144. data/lib/grape/validations/validators/same_as.rb +6 -3
  145. data/lib/grape/validations/validators/values.rb +17 -5
  146. data/lib/grape/version.rb +3 -1
  147. data/spec/grape/api/custom_validations_spec.rb +5 -3
  148. data/spec/grape/api/deeply_included_options_spec.rb +2 -0
  149. data/spec/grape/api/defines_boolean_in_params_spec.rb +5 -3
  150. data/spec/grape/api/inherited_helpers_spec.rb +2 -0
  151. data/spec/grape/api/instance_spec.rb +104 -0
  152. data/spec/grape/api/invalid_format_spec.rb +2 -0
  153. data/spec/grape/api/namespace_parameters_in_route_spec.rb +2 -0
  154. data/spec/grape/api/nested_helpers_spec.rb +2 -0
  155. data/spec/grape/api/optional_parameters_in_route_spec.rb +2 -0
  156. data/spec/grape/api/parameters_modification_spec.rb +3 -1
  157. data/spec/grape/api/patch_method_helpers_spec.rb +2 -0
  158. data/spec/grape/api/recognize_path_spec.rb +2 -0
  159. data/spec/grape/api/required_parameters_in_route_spec.rb +2 -0
  160. data/spec/grape/api/required_parameters_with_invalid_method_spec.rb +2 -0
  161. data/spec/grape/api/routes_with_requirements_spec.rb +2 -0
  162. data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +2 -0
  163. data/spec/grape/api/shared_helpers_spec.rb +2 -0
  164. data/spec/grape/api_remount_spec.rb +2 -0
  165. data/spec/grape/api_spec.rb +99 -11
  166. data/spec/grape/config_spec.rb +2 -0
  167. data/spec/grape/dsl/callbacks_spec.rb +2 -0
  168. data/spec/grape/dsl/configuration_spec.rb +2 -0
  169. data/spec/grape/dsl/desc_spec.rb +2 -0
  170. data/spec/grape/dsl/headers_spec.rb +2 -0
  171. data/spec/grape/dsl/helpers_spec.rb +4 -2
  172. data/spec/grape/dsl/inside_route_spec.rb +177 -33
  173. data/spec/grape/dsl/logger_spec.rb +2 -0
  174. data/spec/grape/dsl/middleware_spec.rb +2 -0
  175. data/spec/grape/dsl/parameters_spec.rb +2 -0
  176. data/spec/grape/dsl/request_response_spec.rb +2 -0
  177. data/spec/grape/dsl/routing_spec.rb +2 -0
  178. data/spec/grape/dsl/settings_spec.rb +2 -0
  179. data/spec/grape/dsl/validations_spec.rb +2 -0
  180. data/spec/grape/endpoint_spec.rb +21 -6
  181. data/spec/grape/entity_spec.rb +2 -0
  182. data/spec/grape/exceptions/base_spec.rb +3 -1
  183. data/spec/grape/exceptions/body_parse_errors_spec.rb +2 -0
  184. data/spec/grape/exceptions/invalid_accept_header_spec.rb +2 -0
  185. data/spec/grape/exceptions/invalid_formatter_spec.rb +2 -0
  186. data/spec/grape/exceptions/invalid_response_spec.rb +2 -0
  187. data/spec/grape/exceptions/invalid_versioner_option_spec.rb +2 -0
  188. data/spec/grape/exceptions/missing_mime_type_spec.rb +2 -0
  189. data/spec/grape/exceptions/missing_option_spec.rb +2 -0
  190. data/spec/grape/exceptions/unknown_options_spec.rb +2 -0
  191. data/spec/grape/exceptions/unknown_validator_spec.rb +2 -0
  192. data/spec/grape/exceptions/validation_errors_spec.rb +4 -2
  193. data/spec/grape/exceptions/validation_spec.rb +3 -1
  194. data/spec/grape/extensions/param_builders/hash_spec.rb +2 -0
  195. data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +2 -0
  196. data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +2 -0
  197. data/spec/grape/integration/global_namespace_function_spec.rb +2 -0
  198. data/spec/grape/integration/rack_sendfile_spec.rb +14 -8
  199. data/spec/grape/integration/rack_spec.rb +3 -1
  200. data/spec/grape/loading_spec.rb +2 -0
  201. data/spec/grape/middleware/auth/base_spec.rb +2 -0
  202. data/spec/grape/middleware/auth/dsl_spec.rb +2 -0
  203. data/spec/grape/middleware/auth/strategies_spec.rb +3 -1
  204. data/spec/grape/middleware/base_spec.rb +2 -0
  205. data/spec/grape/middleware/error_spec.rb +2 -0
  206. data/spec/grape/middleware/exception_spec.rb +3 -1
  207. data/spec/grape/middleware/formatter_spec.rb +19 -12
  208. data/spec/grape/middleware/globals_spec.rb +2 -0
  209. data/spec/grape/middleware/stack_spec.rb +11 -0
  210. data/spec/grape/middleware/versioner/accept_version_header_spec.rb +3 -1
  211. data/spec/grape/middleware/versioner/header_spec.rb +3 -1
  212. data/spec/grape/middleware/versioner/param_spec.rb +3 -1
  213. data/spec/grape/middleware/versioner/path_spec.rb +3 -1
  214. data/spec/grape/middleware/versioner_spec.rb +2 -0
  215. data/spec/grape/named_api_spec.rb +2 -0
  216. data/spec/grape/parser_spec.rb +7 -5
  217. data/spec/grape/path_spec.rb +6 -4
  218. data/spec/grape/presenters/presenter_spec.rb +2 -0
  219. data/spec/grape/request_spec.rb +2 -0
  220. data/spec/grape/util/inheritable_setting_spec.rb +2 -0
  221. data/spec/grape/util/inheritable_values_spec.rb +2 -0
  222. data/spec/grape/util/reverse_stackable_values_spec.rb +2 -0
  223. data/spec/grape/util/stackable_values_spec.rb +3 -1
  224. data/spec/grape/util/strict_hash_configuration_spec.rb +2 -0
  225. data/spec/grape/validations/attributes_iterator_spec.rb +2 -0
  226. data/spec/grape/validations/instance_behaivour_spec.rb +5 -3
  227. data/spec/grape/validations/multiple_attributes_iterator_spec.rb +2 -0
  228. data/spec/grape/validations/params_scope_spec.rb +3 -1
  229. data/spec/grape/validations/single_attribute_iterator_spec.rb +18 -4
  230. data/spec/grape/validations/types/array_coercer_spec.rb +35 -0
  231. data/spec/grape/validations/types/primitive_coercer_spec.rb +135 -0
  232. data/spec/grape/validations/types/set_coercer_spec.rb +34 -0
  233. data/spec/grape/validations/types_spec.rb +9 -36
  234. data/spec/grape/validations/validators/all_or_none_spec.rb +2 -0
  235. data/spec/grape/validations/validators/allow_blank_spec.rb +2 -0
  236. data/spec/grape/validations/validators/at_least_one_of_spec.rb +2 -0
  237. data/spec/grape/validations/validators/coerce_spec.rb +341 -136
  238. data/spec/grape/validations/validators/default_spec.rb +123 -0
  239. data/spec/grape/validations/validators/exactly_one_of_spec.rb +14 -12
  240. data/spec/grape/validations/validators/except_values_spec.rb +3 -1
  241. data/spec/grape/validations/validators/mutual_exclusion_spec.rb +2 -0
  242. data/spec/grape/validations/validators/presence_spec.rb +30 -0
  243. data/spec/grape/validations/validators/regexp_spec.rb +2 -0
  244. data/spec/grape/validations/validators/same_as_spec.rb +2 -0
  245. data/spec/grape/validations/validators/values_spec.rb +30 -5
  246. data/spec/grape/validations_spec.rb +91 -33
  247. data/spec/integration/eager_load/eager_load_spec.rb +15 -0
  248. data/spec/integration/multi_json/json_spec.rb +2 -0
  249. data/spec/integration/multi_xml/xml_spec.rb +2 -0
  250. data/spec/shared/versioning_examples.rb +2 -0
  251. data/spec/spec_helper.rb +18 -0
  252. data/spec/support/basic_auth_encode_helpers.rb +2 -0
  253. data/spec/support/content_type_helpers.rb +2 -0
  254. data/spec/support/eager_load.rb +19 -0
  255. data/spec/support/endpoint_faker.rb +2 -0
  256. data/spec/support/file_streamer.rb +2 -0
  257. data/spec/support/integer_helpers.rb +2 -0
  258. data/spec/support/versioned_helpers.rb +4 -2
  259. metadata +48 -28
  260. data/lib/grape/extensions/deep_hash_with_indifferent_access.rb +0 -18
  261. data/lib/grape/util/content_types.rb +0 -26
  262. data/lib/grape/validations/types/virtus_collection_patch.rb +0 -16
@@ -1,34 +1,33 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'forwardable'
2
4
  require 'mustermann/grape'
5
+ require 'grape/util/cache'
3
6
 
4
7
  module Grape
5
8
  class Router
6
9
  class Pattern
7
- DEFAULT_PATTERN_OPTIONS = { uri_decode: true, type: :grape }.freeze
10
+ DEFAULT_PATTERN_OPTIONS = { uri_decode: true }.freeze
8
11
  DEFAULT_SUPPORTED_CAPTURE = %i[format version].freeze
9
12
 
10
- attr_reader :origin, :path, :capture, :pattern
13
+ attr_reader :origin, :path, :pattern, :to_regexp
11
14
 
12
15
  extend Forwardable
13
16
  def_delegators :pattern, :named_captures, :params
14
- def_delegators :@regexp, :===
17
+ def_delegators :to_regexp, :===
15
18
  alias match? ===
16
19
 
17
20
  def initialize(pattern, **options)
18
21
  @origin = pattern
19
22
  @path = build_path(pattern, **options)
20
- @capture = extract_capture(options)
21
- @pattern = Mustermann.new(@path, pattern_options)
22
- @regexp = to_regexp
23
- end
24
-
25
- def to_regexp
26
- @to_regexp ||= @pattern.to_regexp
23
+ @pattern = Mustermann::Grape.new(@path, **pattern_options(options))
24
+ @to_regexp = @pattern.to_regexp
27
25
  end
28
26
 
29
27
  private
30
28
 
31
- def pattern_options
29
+ def pattern_options(options)
30
+ capture = extract_capture(**options)
32
31
  options = DEFAULT_PATTERN_OPTIONS.dup
33
32
  options[:capture] = capture if capture.present?
34
33
  options
@@ -36,27 +35,32 @@ module Grape
36
35
 
37
36
  def build_path(pattern, anchor: false, suffix: nil, **_options)
38
37
  unless anchor || pattern.end_with?('*path')
38
+ pattern = +pattern
39
39
  pattern << '/' unless pattern.end_with?('/')
40
40
  pattern << '*path'
41
41
  end
42
42
 
43
- pattern = pattern.split('/').tap do |parts|
43
+ pattern = -pattern.split('/').tap do |parts|
44
44
  parts[parts.length - 1] = '?' + parts.last
45
45
  end.join('/') if pattern.end_with?('*path')
46
46
 
47
- pattern + suffix.to_s
47
+ PatternCache[[pattern, suffix]]
48
48
  end
49
49
 
50
50
  def extract_capture(requirements: {}, **options)
51
51
  requirements = {}.merge(requirements)
52
- supported_capture.each_with_object(requirements) do |field, capture|
52
+ DEFAULT_SUPPORTED_CAPTURE.each_with_object(requirements) do |field, capture|
53
53
  option = Array(options[field])
54
54
  capture[field] = option.map(&:to_s) if option.present?
55
55
  end
56
56
  end
57
57
 
58
- def supported_capture
59
- DEFAULT_SUPPORTED_CAPTURE
58
+ class PatternCache < Grape::Util::Cache
59
+ def initialize
60
+ @cache = Hash.new do |h, (pattern, suffix)|
61
+ h[[pattern, suffix]] = -"#{pattern}#{suffix}"
62
+ end
63
+ end
60
64
  end
61
65
  end
62
66
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'grape/router/pattern'
2
4
  require 'grape/router/attribute_translator'
3
5
  require 'forwardable'
@@ -6,16 +8,17 @@ require 'pathname'
6
8
  module Grape
7
9
  class Router
8
10
  class Route
9
- ROUTE_ATTRIBUTE_REGEXP = /route_([_a-zA-Z]\w*)/
10
- SOURCE_LOCATION_REGEXP = /^(.*?):(\d+?)(?::in `.+?')?$/
11
+ ROUTE_ATTRIBUTE_REGEXP = /route_([_a-zA-Z]\w*)/.freeze
12
+ SOURCE_LOCATION_REGEXP = /^(.*?):(\d+?)(?::in `.+?')?$/.freeze
11
13
  FIXED_NAMED_CAPTURES = %w[format version].freeze
12
14
 
13
- attr_accessor :pattern, :translator, :app, :index, :regexp, :options
15
+ attr_accessor :pattern, :translator, :app, :index, :options
14
16
 
15
17
  alias attributes translator
16
18
 
17
19
  extend Forwardable
18
20
  def_delegators :pattern, :path, :origin
21
+ delegate Grape::Router::AttributeTranslator::ROUTE_ATTRIBUTES => :attributes
19
22
 
20
23
  def method_missing(method_id, *arguments)
21
24
  match = ROUTE_ATTRIBUTE_REGEXP.match(method_id.to_s)
@@ -29,26 +32,7 @@ module Grape
29
32
  end
30
33
 
31
34
  def respond_to_missing?(method_id, _)
32
- ROUTE_ATTRIBUTE_REGEXP.match(method_id.to_s)
33
- end
34
-
35
- %i[
36
- prefix
37
- version
38
- settings
39
- format
40
- description
41
- http_codes
42
- headers
43
- entity
44
- details
45
- requirements
46
- request_method
47
- namespace
48
- ].each do |method_name|
49
- define_method method_name do
50
- attributes.public_send method_name
51
- end
35
+ ROUTE_ATTRIBUTE_REGEXP.match?(method_id.to_s)
52
36
  end
53
37
 
54
38
  def route_method
@@ -62,10 +46,12 @@ module Grape
62
46
  end
63
47
 
64
48
  def initialize(method, pattern, **options)
65
- @suffix = options[:suffix]
66
- @options = options.merge(method: method.to_s.upcase)
49
+ method_s = method.to_s
50
+ method_upcase = Grape::Http::Headers.find_supported_method(method_s) || method_s.upcase
51
+
52
+ @options = options.merge(method: method_upcase)
67
53
  @pattern = Pattern.new(pattern, **options)
68
- @translator = AttributeTranslator.new(**options, request_method: method.to_s.upcase)
54
+ @translator = AttributeTranslator.new(**options, request_method: method_upcase)
69
55
  end
70
56
 
71
57
  def exec(env)
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Grape
2
- module ServeFile
4
+ module ServeStream
3
5
  CHUNK_SIZE = 16_384
4
6
 
5
7
  # Class helps send file through API
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Grape
2
- module ServeFile
4
+ module ServeStream
3
5
  # Response should respond to to_path method
4
6
  # for using Rack::SendFile middleware
5
7
  class SendfileResponse < Rack::Response
@@ -1,20 +1,22 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Grape
2
- module ServeFile
3
- # A simple class used to identify responses which represent files and do not
4
+ module ServeStream
5
+ # A simple class used to identify responses which represent streams (or files) and do not
4
6
  # need to be formatted or pre-read by Rack::Response
5
- class FileResponse
6
- attr_reader :file
7
+ class StreamResponse
8
+ attr_reader :stream
7
9
 
8
- # @param file [Object]
9
- def initialize(file)
10
- @file = file
10
+ # @param stream [Object]
11
+ def initialize(stream)
12
+ @stream = stream
11
13
  end
12
14
 
13
15
  # Equality provided mostly for tests.
14
16
  #
15
17
  # @return [Boolean]
16
18
  def ==(other)
17
- file == other.file
19
+ stream == other.stream
18
20
  end
19
21
  end
20
22
  end
@@ -1,10 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Grape
2
4
  module Util
3
5
  # Base for classes which need to operate with own values kept
4
6
  # in the hash and inherited values kept in a Hash-like object.
5
7
  class BaseInheritable
6
- attr_accessor :inherited_values
7
- attr_accessor :new_values
8
+ attr_accessor :inherited_values, :new_values
8
9
 
9
10
  # @param inherited_values [Object] An object implementing an interface
10
11
  # of the Hash class.
@@ -24,10 +25,18 @@ module Grape
24
25
  end
25
26
 
26
27
  def keys
27
- combined = inherited_values.keys
28
- combined.concat(new_values.keys)
29
- combined.uniq!
30
- combined
28
+ if new_values.any?
29
+ combined = inherited_values.keys
30
+ combined.concat(new_values.keys)
31
+ combined.uniq!
32
+ combined
33
+ else
34
+ inherited_values.keys
35
+ end
36
+ end
37
+
38
+ def key?(name)
39
+ inherited_values.key?(name) || new_values.key?(name)
31
40
  end
32
41
  end
33
42
  end
@@ -0,0 +1,20 @@
1
+ # frozen_String_literal: true
2
+
3
+ require 'singleton'
4
+ require 'forwardable'
5
+
6
+ module Grape
7
+ module Util
8
+ class Cache
9
+ include Singleton
10
+
11
+ attr_reader :cache
12
+
13
+ class << self
14
+ extend Forwardable
15
+ def_delegators :cache, :[]
16
+ def_delegators :instance, :cache
17
+ end
18
+ end
19
+ end
20
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Grape
2
4
  module Util
3
5
  class EndpointConfiguration < LazyValueHash
@@ -1,23 +1,25 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Grape
2
4
  module Env
3
- API_VERSION = 'api.version'.freeze
4
- API_ENDPOINT = 'api.endpoint'.freeze
5
- API_REQUEST_INPUT = 'api.request.input'.freeze
6
- API_REQUEST_BODY = 'api.request.body'.freeze
7
- API_TYPE = 'api.type'.freeze
8
- API_SUBTYPE = 'api.subtype'.freeze
9
- API_VENDOR = 'api.vendor'.freeze
10
- API_FORMAT = 'api.format'.freeze
5
+ API_VERSION = 'api.version'
6
+ API_ENDPOINT = 'api.endpoint'
7
+ API_REQUEST_INPUT = 'api.request.input'
8
+ API_REQUEST_BODY = 'api.request.body'
9
+ API_TYPE = 'api.type'
10
+ API_SUBTYPE = 'api.subtype'
11
+ API_VENDOR = 'api.vendor'
12
+ API_FORMAT = 'api.format'
11
13
 
12
- RACK_INPUT = 'rack.input'.freeze
13
- RACK_REQUEST_QUERY_HASH = 'rack.request.query_hash'.freeze
14
- RACK_REQUEST_FORM_HASH = 'rack.request.form_hash'.freeze
15
- RACK_REQUEST_FORM_INPUT = 'rack.request.form_input'.freeze
14
+ RACK_INPUT = 'rack.input'
15
+ RACK_REQUEST_QUERY_HASH = 'rack.request.query_hash'
16
+ RACK_REQUEST_FORM_HASH = 'rack.request.form_hash'
17
+ RACK_REQUEST_FORM_INPUT = 'rack.request.form_input'
16
18
 
17
- GRAPE_REQUEST = 'grape.request'.freeze
18
- GRAPE_REQUEST_HEADERS = 'grape.request.headers'.freeze
19
- GRAPE_REQUEST_PARAMS = 'grape.request.params'.freeze
20
- GRAPE_ROUTING_ARGS = 'grape.routing_args'.freeze
21
- GRAPE_ALLOWED_METHODS = 'grape.allowed_methods'.freeze
19
+ GRAPE_REQUEST = 'grape.request'
20
+ GRAPE_REQUEST_HEADERS = 'grape.request.headers'
21
+ GRAPE_REQUEST_PARAMS = 'grape.request.params'
22
+ GRAPE_ROUTING_ARGS = 'grape.routing_args'
23
+ GRAPE_ALLOWED_METHODS = 'grape.allowed_methods'
22
24
  end
23
25
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Grape
2
4
  module Util
3
5
  # A branchable, inheritable settings object which can store both stackable
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'base_inheritable'
2
4
 
3
5
  module Grape
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Grape
2
4
  if Object.const_defined? :MultiJson
3
5
  Json = ::MultiJson
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Grape
2
4
  module Util
3
5
  class LazyBlock
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Based on https://github.com/HornsAndHooves/lazy_object
4
+
5
+ module Grape
6
+ module Util
7
+ class LazyObject < BasicObject
8
+ attr_reader :callable
9
+
10
+ def initialize(&callable)
11
+ @callable = callable
12
+ end
13
+
14
+ def __target_object__
15
+ @__target_object__ ||= callable.call
16
+ end
17
+
18
+ def ==(other)
19
+ __target_object__ == other
20
+ end
21
+
22
+ def !=(other)
23
+ __target_object__ != other
24
+ end
25
+
26
+ def !
27
+ !__target_object__
28
+ end
29
+
30
+ def method_missing(method_name, *args, &block)
31
+ if __target_object__.respond_to?(method_name)
32
+ __target_object__.send(method_name, *args, &block)
33
+ else
34
+ super
35
+ end
36
+ end
37
+
38
+ def respond_to_missing?(method_name, include_priv = false)
39
+ __target_object__.respond_to?(method_name, include_priv)
40
+ end
41
+ end
42
+ end
43
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Grape
2
4
  module Util
3
5
  class LazyValue
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Grape
2
4
  module Util
3
5
  module Registrable
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'stackable_values'
2
4
 
3
5
  module Grape
@@ -6,6 +8,8 @@ module Grape
6
8
  protected
7
9
 
8
10
  def concat_values(inherited_value, new_value)
11
+ return inherited_value unless new_value
12
+
9
13
  [].tap do |value|
10
14
  value.concat(new_value)
11
15
  value.concat(inherited_value)
@@ -1,31 +1,23 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'base_inheritable'
2
4
 
3
5
  module Grape
4
6
  module Util
5
7
  class StackableValues < BaseInheritable
6
- attr_reader :frozen_values
7
-
8
- def initialize(*_args)
9
- super
10
-
11
- @frozen_values = {}
12
- end
13
-
8
+ # Even if there is no value, an empty array will be returned.
14
9
  def [](name)
15
- return @frozen_values[name] if @frozen_values.key? name
10
+ inherited_value = inherited_values[name]
11
+ new_value = new_values[name]
16
12
 
17
- inherited_value = @inherited_values[name]
18
- new_value = @new_values[name] || []
19
-
20
- return new_value unless inherited_value
13
+ return new_value || [] unless inherited_value
21
14
 
22
15
  concat_values(inherited_value, new_value)
23
16
  end
24
17
 
25
18
  def []=(name, value)
26
- raise if @frozen_values.key? name
27
- @new_values[name] ||= []
28
- @new_values[name].push value
19
+ new_values[name] ||= []
20
+ new_values[name].push value
29
21
  end
30
22
 
31
23
  def to_hash
@@ -34,13 +26,11 @@ module Grape
34
26
  end
35
27
  end
36
28
 
37
- def freeze_value(key)
38
- @frozen_values[key] = self[key].freeze
39
- end
40
-
41
29
  protected
42
30
 
43
31
  def concat_values(inherited_value, new_value)
32
+ return inherited_value unless new_value
33
+
44
34
  [].tap do |value|
45
35
  value.concat(inherited_value)
46
36
  value.concat(new_value)