grape 0.1.1 → 2.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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +1167 -0
- data/CONTRIBUTING.md +156 -0
- data/LICENSE +1 -1
- data/README.md +4192 -0
- data/UPGRADING.md +1697 -0
- data/grape.gemspec +28 -105
- data/grape.png +0 -0
- data/lib/grape/api/helpers.rb +9 -0
- data/lib/grape/api/instance.rb +247 -0
- data/lib/grape/api.rb +158 -194
- data/lib/grape/content_types.rb +31 -0
- data/lib/grape/cookies.rb +50 -0
- data/lib/grape/dry_types.rb +10 -0
- data/lib/grape/dsl/api.rb +17 -0
- data/lib/grape/dsl/callbacks.rb +69 -0
- data/lib/grape/dsl/configuration.rb +15 -0
- data/lib/grape/dsl/desc.rb +124 -0
- data/lib/grape/dsl/headers.rb +21 -0
- data/lib/grape/dsl/helpers.rb +108 -0
- data/lib/grape/dsl/inside_route.rb +454 -0
- data/lib/grape/dsl/logger.rb +22 -0
- data/lib/grape/dsl/middleware.rb +54 -0
- data/lib/grape/dsl/parameters.rb +266 -0
- data/lib/grape/dsl/request_response.rb +171 -0
- data/lib/grape/dsl/routing.rb +248 -0
- data/lib/grape/dsl/settings.rb +179 -0
- data/lib/grape/dsl/validations.rb +57 -0
- data/lib/grape/endpoint.rb +398 -68
- data/lib/grape/env.rb +20 -0
- data/lib/grape/error_formatter/base.rb +68 -0
- data/lib/grape/error_formatter/json.rb +28 -0
- data/lib/grape/error_formatter/serializable_hash.rb +7 -0
- data/lib/grape/error_formatter/txt.rb +21 -0
- data/lib/grape/error_formatter/xml.rb +11 -0
- data/lib/grape/error_formatter.rb +15 -0
- data/lib/grape/exceptions/base.rb +76 -0
- data/lib/grape/exceptions/conflicting_types.rb +11 -0
- data/lib/grape/exceptions/empty_message_body.rb +11 -0
- data/lib/grape/exceptions/incompatible_option_values.rb +11 -0
- data/lib/grape/exceptions/invalid_accept_header.rb +11 -0
- data/lib/grape/exceptions/invalid_formatter.rb +11 -0
- data/lib/grape/exceptions/invalid_message_body.rb +11 -0
- data/lib/grape/exceptions/invalid_parameters.rb +11 -0
- data/lib/grape/exceptions/invalid_response.rb +11 -0
- data/lib/grape/exceptions/invalid_version_header.rb +11 -0
- data/lib/grape/exceptions/invalid_versioner_option.rb +11 -0
- data/lib/grape/exceptions/invalid_with_option_for_represent.rb +11 -0
- data/lib/grape/exceptions/method_not_allowed.rb +11 -0
- data/lib/grape/exceptions/missing_group_type.rb +13 -0
- data/lib/grape/exceptions/missing_mime_type.rb +11 -0
- data/lib/grape/exceptions/missing_option.rb +11 -0
- data/lib/grape/exceptions/missing_vendor_option.rb +11 -0
- data/lib/grape/exceptions/too_deep_parameters.rb +11 -0
- data/lib/grape/exceptions/too_many_multipart_files.rb +11 -0
- data/lib/grape/exceptions/unknown_auth_strategy.rb +11 -0
- data/lib/grape/exceptions/unknown_options.rb +11 -0
- data/lib/grape/exceptions/unknown_parameter.rb +11 -0
- data/lib/grape/exceptions/unknown_params_builder.rb +11 -0
- data/lib/grape/exceptions/unknown_validator.rb +11 -0
- data/lib/grape/exceptions/unsupported_group_type.rb +13 -0
- data/lib/grape/exceptions/validation.rb +25 -0
- data/lib/grape/exceptions/validation_array_errors.rb +14 -0
- data/lib/grape/exceptions/validation_errors.rb +53 -0
- data/lib/grape/extensions/active_support/hash_with_indifferent_access.rb +24 -0
- data/lib/grape/extensions/hash.rb +27 -0
- data/lib/grape/extensions/hashie/mash.rb +24 -0
- data/lib/grape/formatter/base.rb +16 -0
- data/lib/grape/formatter/json.rb +13 -0
- data/lib/grape/formatter/serializable_hash.rb +39 -0
- data/lib/grape/formatter/txt.rb +11 -0
- data/lib/grape/formatter/xml.rb +13 -0
- data/lib/grape/formatter.rb +17 -0
- data/lib/grape/json.rb +10 -0
- data/lib/grape/locale/en.yml +59 -0
- data/lib/grape/middleware/auth/base.rb +23 -0
- data/lib/grape/middleware/auth/dsl.rb +39 -0
- data/lib/grape/middleware/auth/strategies.rb +25 -0
- data/lib/grape/middleware/auth/strategy_info.rb +15 -0
- data/lib/grape/middleware/base.rb +89 -18
- data/lib/grape/middleware/error.rb +129 -10
- data/lib/grape/middleware/filter.rb +19 -0
- data/lib/grape/middleware/formatter.rb +124 -82
- data/lib/grape/middleware/globals.rb +14 -0
- data/lib/grape/middleware/stack.rb +109 -0
- data/lib/grape/middleware/versioner/accept_version_header.rb +38 -0
- data/lib/grape/middleware/versioner/base.rb +74 -0
- data/lib/grape/middleware/versioner/header.rb +127 -0
- data/lib/grape/middleware/versioner/param.rb +32 -0
- data/lib/grape/middleware/versioner/path.rb +40 -0
- data/lib/grape/middleware/versioner.rb +21 -21
- data/lib/grape/namespace.rb +46 -0
- data/lib/grape/params_builder/base.rb +18 -0
- data/lib/grape/params_builder/hash.rb +11 -0
- data/lib/grape/params_builder/hash_with_indifferent_access.rb +11 -0
- data/lib/grape/params_builder/hashie_mash.rb +11 -0
- data/lib/grape/params_builder.rb +32 -0
- data/lib/grape/parser/base.rb +16 -0
- data/lib/grape/parser/json.rb +14 -0
- data/lib/grape/parser/xml.rb +14 -0
- data/lib/grape/parser.rb +15 -0
- data/lib/grape/path.rb +76 -0
- data/lib/grape/presenters/presenter.rb +11 -0
- data/lib/grape/railtie.rb +9 -0
- data/lib/grape/request.rb +190 -0
- data/lib/grape/router/base_route.rb +39 -0
- data/lib/grape/router/greedy_route.rb +20 -0
- data/lib/grape/router/pattern.rb +81 -0
- data/lib/grape/router/route.rb +62 -0
- data/lib/grape/router.rb +190 -0
- data/lib/grape/serve_stream/file_body.rb +36 -0
- data/lib/grape/serve_stream/sendfile_response.rb +21 -0
- data/lib/grape/serve_stream/stream_response.rb +23 -0
- data/lib/grape/types/invalid_value.rb +8 -0
- data/lib/grape/util/base_inheritable.rb +43 -0
- data/lib/grape/util/cache.rb +17 -0
- data/lib/grape/util/endpoint_configuration.rb +8 -0
- data/lib/grape/util/header.rb +13 -0
- data/lib/grape/util/inheritable_setting.rb +100 -0
- data/lib/grape/util/inheritable_values.rb +29 -0
- data/lib/grape/util/lazy/block.rb +29 -0
- data/lib/grape/util/lazy/value.rb +38 -0
- data/lib/grape/util/lazy/value_array.rb +21 -0
- data/lib/grape/util/lazy/value_enumerable.rb +34 -0
- data/lib/grape/util/lazy/value_hash.rb +21 -0
- data/lib/grape/util/media_type.rb +70 -0
- data/lib/grape/util/registry.rb +27 -0
- data/lib/grape/util/reverse_stackable_values.rb +15 -0
- data/lib/grape/util/stackable_values.rb +36 -0
- data/lib/grape/util/strict_hash_configuration.rb +108 -0
- data/lib/grape/validations/attributes_doc.rb +60 -0
- data/lib/grape/validations/attributes_iterator.rb +62 -0
- data/lib/grape/validations/contract_scope.rb +34 -0
- data/lib/grape/validations/multiple_attributes_iterator.rb +13 -0
- data/lib/grape/validations/params_scope.rb +538 -0
- data/lib/grape/validations/single_attribute_iterator.rb +26 -0
- data/lib/grape/validations/types/array_coercer.rb +61 -0
- data/lib/grape/validations/types/custom_type_coercer.rb +164 -0
- data/lib/grape/validations/types/custom_type_collection_coercer.rb +56 -0
- data/lib/grape/validations/types/dry_type_coercer.rb +66 -0
- data/lib/grape/validations/types/file.rb +31 -0
- data/lib/grape/validations/types/invalid_value.rb +17 -0
- data/lib/grape/validations/types/json.rb +71 -0
- data/lib/grape/validations/types/multiple_type_coercer.rb +57 -0
- data/lib/grape/validations/types/primitive_coercer.rb +73 -0
- data/lib/grape/validations/types/set_coercer.rb +35 -0
- data/lib/grape/validations/types/variant_collection_coercer.rb +51 -0
- data/lib/grape/validations/types.rb +213 -0
- data/lib/grape/validations/validator_factory.rb +15 -0
- data/lib/grape/validations/validators/all_or_none_of_validator.rb +16 -0
- data/lib/grape/validations/validators/allow_blank_validator.rb +20 -0
- data/lib/grape/validations/validators/as_validator.rb +14 -0
- data/lib/grape/validations/validators/at_least_one_of_validator.rb +15 -0
- data/lib/grape/validations/validators/base.rb +88 -0
- data/lib/grape/validations/validators/coerce_validator.rb +75 -0
- data/lib/grape/validations/validators/contract_scope_validator.rb +41 -0
- data/lib/grape/validations/validators/default_validator.rb +37 -0
- data/lib/grape/validations/validators/exactly_one_of_validator.rb +17 -0
- data/lib/grape/validations/validators/except_values_validator.rb +24 -0
- data/lib/grape/validations/validators/length_validator.rb +49 -0
- data/lib/grape/validations/validators/multiple_params_base.rb +34 -0
- data/lib/grape/validations/validators/mutual_exclusion_validator.rb +16 -0
- data/lib/grape/validations/validators/presence_validator.rb +15 -0
- data/lib/grape/validations/validators/regexp_validator.rb +16 -0
- data/lib/grape/validations/validators/same_as_validator.rb +29 -0
- data/lib/grape/validations/validators/values_validator.rb +60 -0
- data/lib/grape/validations.rb +21 -0
- data/lib/grape/version.rb +6 -0
- data/lib/grape/xml.rb +10 -0
- data/lib/grape.rb +81 -17
- metadata +250 -192
- data/.document +0 -5
- data/.gitignore +0 -23
- data/.rspec +0 -2
- data/.rvmrc +0 -1
- data/Gemfile +0 -21
- data/Gemfile.lock +0 -58
- data/README.markdown +0 -75
- data/Rakefile +0 -70
- data/VERSION +0 -1
- data/autotest/discover.rb +0 -1
- data/lib/grape/middleware/auth/basic.rb +0 -30
- data/lib/grape/middleware/auth/oauth2.rb +0 -55
- data/lib/grape/middleware/prefixer.rb +0 -21
- data/lib/grape/middleware_stack.rb +0 -35
- data/spec/grape/api_spec.rb +0 -343
- data/spec/grape/endpoint_spec.rb +0 -104
- data/spec/grape/middleware/auth/basic_spec.rb +0 -31
- data/spec/grape/middleware/auth/oauth2_spec.rb +0 -88
- data/spec/grape/middleware/base_spec.rb +0 -63
- data/spec/grape/middleware/error_spec.rb +0 -49
- data/spec/grape/middleware/formatter_spec.rb +0 -87
- data/spec/grape/middleware/prefixer_spec.rb +0 -30
- data/spec/grape/middleware/versioner_spec.rb +0 -40
- data/spec/grape/middleware_stack_spec.rb +0 -47
- data/spec/grape_spec.rb +0 -1
- data/spec/spec_helper.rb +0 -20
data/grape.gemspec
CHANGED
|
@@ -1,110 +1,33 @@
|
|
|
1
|
-
#
|
|
2
|
-
# DO NOT EDIT THIS FILE DIRECTLY
|
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
|
4
|
-
# -*- encoding: utf-8 -*-
|
|
1
|
+
# frozen_string_literal: true
|
|
5
2
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
s.version = "0.1.1"
|
|
3
|
+
$LOAD_PATH.unshift File.expand_path('lib', __dir__)
|
|
4
|
+
require 'grape/version'
|
|
9
5
|
|
|
10
|
-
|
|
11
|
-
s.
|
|
12
|
-
s.
|
|
13
|
-
s.
|
|
14
|
-
s.
|
|
15
|
-
s.
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
s.
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
"README.markdown",
|
|
28
|
-
"Rakefile",
|
|
29
|
-
"VERSION",
|
|
30
|
-
"autotest/discover.rb",
|
|
31
|
-
"grape.gemspec",
|
|
32
|
-
"lib/grape.rb",
|
|
33
|
-
"lib/grape/api.rb",
|
|
34
|
-
"lib/grape/endpoint.rb",
|
|
35
|
-
"lib/grape/middleware/auth/basic.rb",
|
|
36
|
-
"lib/grape/middleware/auth/oauth2.rb",
|
|
37
|
-
"lib/grape/middleware/base.rb",
|
|
38
|
-
"lib/grape/middleware/error.rb",
|
|
39
|
-
"lib/grape/middleware/formatter.rb",
|
|
40
|
-
"lib/grape/middleware/prefixer.rb",
|
|
41
|
-
"lib/grape/middleware/versioner.rb",
|
|
42
|
-
"lib/grape/middleware_stack.rb",
|
|
43
|
-
"spec/grape/api_spec.rb",
|
|
44
|
-
"spec/grape/endpoint_spec.rb",
|
|
45
|
-
"spec/grape/middleware/auth/basic_spec.rb",
|
|
46
|
-
"spec/grape/middleware/auth/oauth2_spec.rb",
|
|
47
|
-
"spec/grape/middleware/base_spec.rb",
|
|
48
|
-
"spec/grape/middleware/error_spec.rb",
|
|
49
|
-
"spec/grape/middleware/formatter_spec.rb",
|
|
50
|
-
"spec/grape/middleware/prefixer_spec.rb",
|
|
51
|
-
"spec/grape/middleware/versioner_spec.rb",
|
|
52
|
-
"spec/grape/middleware_stack_spec.rb",
|
|
53
|
-
"spec/grape_spec.rb",
|
|
54
|
-
"spec/spec_helper.rb"
|
|
55
|
-
]
|
|
56
|
-
s.homepage = %q{http://github.com/intridea/grape}
|
|
57
|
-
s.rdoc_options = ["--charset=UTF-8"]
|
|
58
|
-
s.require_paths = ["lib"]
|
|
59
|
-
s.rubygems_version = %q{1.3.7}
|
|
60
|
-
s.summary = %q{A Ruby framework for rapid API development.}
|
|
61
|
-
s.test_files = [
|
|
62
|
-
"spec/grape/api_spec.rb",
|
|
63
|
-
"spec/grape/endpoint_spec.rb",
|
|
64
|
-
"spec/grape/middleware/auth/basic_spec.rb",
|
|
65
|
-
"spec/grape/middleware/auth/oauth2_spec.rb",
|
|
66
|
-
"spec/grape/middleware/base_spec.rb",
|
|
67
|
-
"spec/grape/middleware/error_spec.rb",
|
|
68
|
-
"spec/grape/middleware/formatter_spec.rb",
|
|
69
|
-
"spec/grape/middleware/prefixer_spec.rb",
|
|
70
|
-
"spec/grape/middleware/versioner_spec.rb",
|
|
71
|
-
"spec/grape/middleware_stack_spec.rb",
|
|
72
|
-
"spec/grape_spec.rb",
|
|
73
|
-
"spec/spec_helper.rb"
|
|
74
|
-
]
|
|
6
|
+
Gem::Specification.new do |s|
|
|
7
|
+
s.name = 'grape'
|
|
8
|
+
s.version = Grape::VERSION
|
|
9
|
+
s.platform = Gem::Platform::RUBY
|
|
10
|
+
s.authors = ['Michael Bleigh']
|
|
11
|
+
s.email = ['michael@intridea.com']
|
|
12
|
+
s.homepage = 'https://github.com/ruby-grape/grape'
|
|
13
|
+
s.summary = 'A simple Ruby framework for building REST-like APIs.'
|
|
14
|
+
s.description = 'A Ruby framework for rapid API development with great conventions.'
|
|
15
|
+
s.license = 'MIT'
|
|
16
|
+
s.metadata = {
|
|
17
|
+
'bug_tracker_uri' => 'https://github.com/ruby-grape/grape/issues',
|
|
18
|
+
'changelog_uri' => "https://github.com/ruby-grape/grape/blob/v#{s.version}/CHANGELOG.md",
|
|
19
|
+
'documentation_uri' => "https://www.rubydoc.info/gems/grape/#{s.version}",
|
|
20
|
+
'source_code_uri' => "https://github.com/ruby-grape/grape/tree/v#{s.version}",
|
|
21
|
+
'rubygems_mfa_required' => 'true'
|
|
22
|
+
}
|
|
75
23
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
24
|
+
s.add_dependency 'activesupport', '>= 6.1'
|
|
25
|
+
s.add_dependency 'dry-types', '>= 1.1'
|
|
26
|
+
s.add_dependency 'mustermann-grape', '~> 1.1.0'
|
|
27
|
+
s.add_dependency 'rack', '>= 2'
|
|
28
|
+
s.add_dependency 'zeitwerk'
|
|
79
29
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
s.add_runtime_dependency(%q<rack-jsonp>, [">= 0"])
|
|
84
|
-
s.add_runtime_dependency(%q<json>, [">= 0"])
|
|
85
|
-
s.add_runtime_dependency(%q<multi_json>, [">= 0"])
|
|
86
|
-
s.add_runtime_dependency(%q<multi_xml>, [">= 0"])
|
|
87
|
-
s.add_development_dependency(%q<rake>, [">= 0"])
|
|
88
|
-
s.add_development_dependency(%q<jeweler>, [">= 0"])
|
|
89
|
-
else
|
|
90
|
-
s.add_dependency(%q<rack>, [">= 0"])
|
|
91
|
-
s.add_dependency(%q<rack-mount>, ["~> 0.6.13"])
|
|
92
|
-
s.add_dependency(%q<rack-jsonp>, [">= 0"])
|
|
93
|
-
s.add_dependency(%q<json>, [">= 0"])
|
|
94
|
-
s.add_dependency(%q<multi_json>, [">= 0"])
|
|
95
|
-
s.add_dependency(%q<multi_xml>, [">= 0"])
|
|
96
|
-
s.add_dependency(%q<rake>, [">= 0"])
|
|
97
|
-
s.add_dependency(%q<jeweler>, [">= 0"])
|
|
98
|
-
end
|
|
99
|
-
else
|
|
100
|
-
s.add_dependency(%q<rack>, [">= 0"])
|
|
101
|
-
s.add_dependency(%q<rack-mount>, ["~> 0.6.13"])
|
|
102
|
-
s.add_dependency(%q<rack-jsonp>, [">= 0"])
|
|
103
|
-
s.add_dependency(%q<json>, [">= 0"])
|
|
104
|
-
s.add_dependency(%q<multi_json>, [">= 0"])
|
|
105
|
-
s.add_dependency(%q<multi_xml>, [">= 0"])
|
|
106
|
-
s.add_dependency(%q<rake>, [">= 0"])
|
|
107
|
-
s.add_dependency(%q<jeweler>, [">= 0"])
|
|
108
|
-
end
|
|
30
|
+
s.files = Dir['lib/**/*', 'CHANGELOG.md', 'CONTRIBUTING.md', 'README.md', 'grape.png', 'UPGRADING.md', 'LICENSE', 'grape.gemspec']
|
|
31
|
+
s.require_paths = ['lib']
|
|
32
|
+
s.required_ruby_version = '>= 2.7.0'
|
|
109
33
|
end
|
|
110
|
-
|
data/grape.png
ADDED
|
Binary file
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Grape
|
|
4
|
+
class API
|
|
5
|
+
# The API Instance class, is the engine behind Grape::API. Each class that inherits
|
|
6
|
+
# from this will represent a different API instance
|
|
7
|
+
class Instance
|
|
8
|
+
extend Grape::Middleware::Auth::DSL
|
|
9
|
+
include Grape::DSL::API
|
|
10
|
+
|
|
11
|
+
class << self
|
|
12
|
+
attr_reader :instance, :base
|
|
13
|
+
attr_accessor :configuration
|
|
14
|
+
|
|
15
|
+
def given(conditional_option, &block)
|
|
16
|
+
evaluate_as_instance_with_configuration(block, lazy: true) if conditional_option && block
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def mounted(&block)
|
|
20
|
+
evaluate_as_instance_with_configuration(block, lazy: true)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def base=(grape_api)
|
|
24
|
+
@base = grape_api
|
|
25
|
+
grape_api.instances << self
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def to_s
|
|
29
|
+
base&.to_s || super
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def base_instance?
|
|
33
|
+
self == base.base_instance
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# A class-level lock to ensure the API is not compiled by multiple
|
|
37
|
+
# threads simultaneously within the same process.
|
|
38
|
+
LOCK = Mutex.new
|
|
39
|
+
|
|
40
|
+
# Clears all defined routes, endpoints, etc., on this API.
|
|
41
|
+
def reset!
|
|
42
|
+
reset_endpoints!
|
|
43
|
+
reset_routes!
|
|
44
|
+
reset_validations!
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Parses the API's definition and compiles it into an instance of
|
|
48
|
+
# Grape::API.
|
|
49
|
+
def compile
|
|
50
|
+
@instance ||= new # rubocop:disable Naming/MemoizedInstanceVariableName
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Wipe the compiled API so we can recompile after changes were made.
|
|
54
|
+
def change!
|
|
55
|
+
@instance = nil
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# This is the interface point between Rack and Grape; it accepts a request
|
|
59
|
+
# from Rack and ultimately returns an array of three values: the status,
|
|
60
|
+
# the headers, and the body. See [the rack specification]
|
|
61
|
+
# (http://www.rubydoc.info/github/rack/rack/master/file/SPEC) for more.
|
|
62
|
+
def call(env)
|
|
63
|
+
compile!
|
|
64
|
+
call!(env)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# A non-synchronized version of ::call.
|
|
68
|
+
def call!(env)
|
|
69
|
+
instance.call(env)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# (see #cascade?)
|
|
73
|
+
def cascade(value = nil)
|
|
74
|
+
if value.nil?
|
|
75
|
+
inheritable_setting.namespace_inheritable.key?(:cascade) ? !namespace_inheritable(:cascade).nil? : true
|
|
76
|
+
else
|
|
77
|
+
namespace_inheritable(:cascade, value)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def compile!
|
|
82
|
+
return if instance
|
|
83
|
+
|
|
84
|
+
LOCK.synchronize { compile unless instance }
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# see Grape::Router#recognize_path
|
|
88
|
+
def recognize_path(path)
|
|
89
|
+
compile!
|
|
90
|
+
instance.router.recognize_path(path)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
protected
|
|
94
|
+
|
|
95
|
+
def prepare_routes
|
|
96
|
+
endpoints.map(&:routes).flatten
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Execute first the provided block, then each of the
|
|
100
|
+
# block passed in. Allows for simple 'before' setups
|
|
101
|
+
# of settings stack pushes.
|
|
102
|
+
def nest(*blocks, &block)
|
|
103
|
+
blocks.compact!
|
|
104
|
+
if blocks.any?
|
|
105
|
+
evaluate_as_instance_with_configuration(block) if block
|
|
106
|
+
blocks.each { |b| evaluate_as_instance_with_configuration(b) }
|
|
107
|
+
reset_validations!
|
|
108
|
+
else
|
|
109
|
+
instance_eval(&block)
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def evaluate_as_instance_with_configuration(block, lazy: false)
|
|
114
|
+
lazy_block = Grape::Util::Lazy::Block.new do |configuration|
|
|
115
|
+
value_for_configuration = configuration
|
|
116
|
+
self.configuration = value_for_configuration.evaluate if value_for_configuration.try(:lazy?)
|
|
117
|
+
response = instance_eval(&block)
|
|
118
|
+
self.configuration = value_for_configuration
|
|
119
|
+
response
|
|
120
|
+
end
|
|
121
|
+
if base && base_instance? && lazy
|
|
122
|
+
lazy_block
|
|
123
|
+
else
|
|
124
|
+
lazy_block.evaluate_from(configuration)
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def inherited(subclass)
|
|
129
|
+
super
|
|
130
|
+
subclass.reset!
|
|
131
|
+
subclass.logger = logger.clone
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def inherit_settings(other_settings)
|
|
135
|
+
top_level_setting.inherit_from other_settings.point_in_time_copy
|
|
136
|
+
|
|
137
|
+
# Propagate any inherited params down to our endpoints, and reset any
|
|
138
|
+
# compiled routes.
|
|
139
|
+
endpoints.each do |e|
|
|
140
|
+
e.inherit_settings(top_level_setting.namespace_stackable)
|
|
141
|
+
e.reset_routes!
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
reset_routes!
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
attr_reader :router
|
|
149
|
+
|
|
150
|
+
# Builds the routes from the defined endpoints, effectively compiling
|
|
151
|
+
# this API into a usable form.
|
|
152
|
+
def initialize
|
|
153
|
+
@router = Router.new
|
|
154
|
+
add_head_not_allowed_methods_and_options_methods
|
|
155
|
+
self.class.endpoints.each do |endpoint|
|
|
156
|
+
endpoint.mount_in(@router)
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
@router.compile!
|
|
160
|
+
@router.freeze
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# Handle a request. See Rack documentation for what `env` is.
|
|
164
|
+
def call(env)
|
|
165
|
+
status, headers, response = @router.call(env)
|
|
166
|
+
unless cascade?
|
|
167
|
+
headers = Grape::Util::Header.new.merge(headers)
|
|
168
|
+
headers.delete('X-Cascade')
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
[status, headers, response]
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# Some requests may return a HTTP 404 error if grape cannot find a matching
|
|
175
|
+
# route. In this case, Grape::Router adds a X-Cascade header to the response
|
|
176
|
+
# and sets it to 'pass', indicating to grape's parents they should keep
|
|
177
|
+
# looking for a matching route on other resources.
|
|
178
|
+
#
|
|
179
|
+
# In some applications (e.g. mounting grape on rails), one might need to trap
|
|
180
|
+
# errors from reaching upstream. This is effectivelly done by unsetting
|
|
181
|
+
# X-Cascade. Default :cascade is true.
|
|
182
|
+
def cascade?
|
|
183
|
+
return self.class.namespace_inheritable(:cascade) if self.class.inheritable_setting.namespace_inheritable.key?(:cascade)
|
|
184
|
+
return self.class.namespace_inheritable(:version_options)[:cascade] if self.class.namespace_inheritable(:version_options)&.key?(:cascade)
|
|
185
|
+
|
|
186
|
+
true
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
reset!
|
|
190
|
+
|
|
191
|
+
private
|
|
192
|
+
|
|
193
|
+
# For every resource add a 'OPTIONS' route that returns an HTTP 204 response
|
|
194
|
+
# with a list of HTTP methods that can be called. Also add a route that
|
|
195
|
+
# will return an HTTP 405 response for any HTTP method that the resource
|
|
196
|
+
# cannot handle.
|
|
197
|
+
def add_head_not_allowed_methods_and_options_methods
|
|
198
|
+
# The paths we collected are prepared (cf. Path#prepare), so they
|
|
199
|
+
# contain already versioning information when using path versioning.
|
|
200
|
+
all_routes = self.class.endpoints.map(&:routes).flatten
|
|
201
|
+
|
|
202
|
+
# Disable versioning so adding a route won't prepend versioning
|
|
203
|
+
# informations again.
|
|
204
|
+
without_root_prefix_and_versioning { collect_route_config_per_pattern(all_routes) }
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def collect_route_config_per_pattern(all_routes)
|
|
208
|
+
routes_by_regexp = all_routes.group_by(&:pattern_regexp)
|
|
209
|
+
|
|
210
|
+
# Build the configuration based on the first endpoint and the collection of methods supported.
|
|
211
|
+
routes_by_regexp.each_value do |routes|
|
|
212
|
+
last_route = routes.last # Most of the configuration is taken from the last endpoint
|
|
213
|
+
next if routes.any? { |route| route.request_method == '*' }
|
|
214
|
+
|
|
215
|
+
allowed_methods = routes.map(&:request_method)
|
|
216
|
+
allowed_methods |= [Rack::HEAD] if !self.class.namespace_inheritable(:do_not_route_head) && allowed_methods.include?(Rack::GET)
|
|
217
|
+
|
|
218
|
+
allow_header = self.class.namespace_inheritable(:do_not_route_options) ? allowed_methods : [Rack::OPTIONS] | allowed_methods
|
|
219
|
+
last_route.app.options[:options_route_enabled] = true unless self.class.namespace_inheritable(:do_not_route_options) || allowed_methods.include?(Rack::OPTIONS)
|
|
220
|
+
|
|
221
|
+
@router.associate_routes(last_route.pattern, {
|
|
222
|
+
endpoint: last_route.app,
|
|
223
|
+
allow_header: allow_header
|
|
224
|
+
})
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
# Allows definition of endpoints that ignore the versioning configuration
|
|
229
|
+
# used by the rest of your API.
|
|
230
|
+
def without_root_prefix_and_versioning
|
|
231
|
+
old_version = self.class.namespace_inheritable(:version)
|
|
232
|
+
old_version_options = self.class.namespace_inheritable(:version_options)
|
|
233
|
+
old_root_prefix = self.class.namespace_inheritable(:root_prefix)
|
|
234
|
+
|
|
235
|
+
self.class.namespace_inheritable_to_nil(:version)
|
|
236
|
+
self.class.namespace_inheritable_to_nil(:version_options)
|
|
237
|
+
self.class.namespace_inheritable_to_nil(:root_prefix)
|
|
238
|
+
|
|
239
|
+
yield
|
|
240
|
+
|
|
241
|
+
self.class.namespace_inheritable(:version, old_version)
|
|
242
|
+
self.class.namespace_inheritable(:version_options, old_version_options)
|
|
243
|
+
self.class.namespace_inheritable(:root_prefix, old_root_prefix)
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
end
|