apipie-rails-jq 1.4.3.pre.beta.pre.jq.1
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/.github/workflows/build.yml +32 -0
- data/.github/workflows/rubocop-challenger.yml +26 -0
- data/.github/workflows/rubocop.yml +18 -0
- data/.gitignore +16 -0
- data/.rspec +2 -0
- data/.rubocop.yml +132 -0
- data/.rubocop_todo.yml +1967 -0
- data/.vscode/settings.json +3 -0
- data/APACHE-LICENSE-2.0 +202 -0
- data/CHANGELOG.md +693 -0
- data/Gemfile +19 -0
- data/MIT-LICENSE +20 -0
- data/NOTICE +4 -0
- data/PROPOSAL_FOR_RESPONSE_DESCRIPTIONS.md +244 -0
- data/README.md +2088 -0
- data/Rakefile +8 -0
- data/apipie-rails.gemspec +44 -0
- data/app/controllers/apipie/apipies_controller.rb +184 -0
- data/app/helpers/apipie_helper.rb +10 -0
- data/app/public/apipie/javascripts/apipie.js +6 -0
- data/app/public/apipie/javascripts/bundled/bootstrap-collapse.js +167 -0
- data/app/public/apipie/javascripts/bundled/bootstrap.js +2280 -0
- data/app/public/apipie/javascripts/bundled/jquery.js +2 -0
- data/app/public/apipie/javascripts/bundled/prettify.js +28 -0
- data/app/public/apipie/stylesheets/application.css +7 -0
- data/app/public/apipie/stylesheets/bundled/bootstrap-responsive.min.css +9 -0
- data/app/public/apipie/stylesheets/bundled/bootstrap.min.css +9 -0
- data/app/public/apipie/stylesheets/bundled/prettify.css +30 -0
- data/app/views/apipie/apipies/_deprecation.html.erb +16 -0
- data/app/views/apipie/apipies/_disqus.html.erb +13 -0
- data/app/views/apipie/apipies/_errors.html.erb +23 -0
- data/app/views/apipie/apipies/_headers.html.erb +26 -0
- data/app/views/apipie/apipies/_languages.erb +6 -0
- data/app/views/apipie/apipies/_metadata.erb +1 -0
- data/app/views/apipie/apipies/_method_detail.erb +63 -0
- data/app/views/apipie/apipies/_params.html.erb +49 -0
- data/app/views/apipie/apipies/_params_plain.html.erb +21 -0
- data/app/views/apipie/apipies/apipie_404.html.erb +17 -0
- data/app/views/apipie/apipies/apipie_checksum.json.erb +1 -0
- data/app/views/apipie/apipies/getting_started.html.erb +6 -0
- data/app/views/apipie/apipies/index.html.erb +56 -0
- data/app/views/apipie/apipies/method.html.erb +41 -0
- data/app/views/apipie/apipies/plain.html.erb +77 -0
- data/app/views/apipie/apipies/resource.html.erb +80 -0
- data/app/views/apipie/apipies/static.html.erb +103 -0
- data/app/views/layouts/apipie/apipie.html.erb +27 -0
- data/config/locales/de.yml +28 -0
- data/config/locales/en.yml +41 -0
- data/config/locales/es.yml +28 -0
- data/config/locales/fr.yml +31 -0
- data/config/locales/it.yml +41 -0
- data/config/locales/ja.yml +31 -0
- data/config/locales/ko.yml +32 -0
- data/config/locales/pl.yml +28 -0
- data/config/locales/pt-BR.yml +28 -0
- data/config/locales/ru.yml +28 -0
- data/config/locales/tr.yml +28 -0
- data/config/locales/zh-CN.yml +28 -0
- data/config/locales/zh-TW.yml +28 -0
- data/gemfiles/Gemfile.tools +9 -0
- data/images/screenshot-1.png +0 -0
- data/images/screenshot-2.png +0 -0
- data/lib/apipie/apipie_module.rb +83 -0
- data/lib/apipie/application.rb +499 -0
- data/lib/apipie/configuration.rb +196 -0
- data/lib/apipie/core_ext/route.rb +9 -0
- data/lib/apipie/dsl_definition.rb +630 -0
- data/lib/apipie/error_description.rb +46 -0
- data/lib/apipie/errors.rb +86 -0
- data/lib/apipie/extractor/collector.rb +116 -0
- data/lib/apipie/extractor/recorder.rb +193 -0
- data/lib/apipie/extractor/writer.rb +454 -0
- data/lib/apipie/extractor.rb +181 -0
- data/lib/apipie/generator/config.rb +12 -0
- data/lib/apipie/generator/generator.rb +2 -0
- data/lib/apipie/generator/swagger/computed_interface_id.rb +23 -0
- data/lib/apipie/generator/swagger/config.rb +80 -0
- data/lib/apipie/generator/swagger/context.rb +38 -0
- data/lib/apipie/generator/swagger/method_description/api_decorator.rb +20 -0
- data/lib/apipie/generator/swagger/method_description/api_schema_service.rb +89 -0
- data/lib/apipie/generator/swagger/method_description/decorator.rb +22 -0
- data/lib/apipie/generator/swagger/method_description/parameters_service.rb +139 -0
- data/lib/apipie/generator/swagger/method_description/response_schema_service.rb +46 -0
- data/lib/apipie/generator/swagger/method_description/response_service.rb +71 -0
- data/lib/apipie/generator/swagger/method_description.rb +2 -0
- data/lib/apipie/generator/swagger/operation_id.rb +51 -0
- data/lib/apipie/generator/swagger/param_description/builder.rb +114 -0
- data/lib/apipie/generator/swagger/param_description/composite.rb +119 -0
- data/lib/apipie/generator/swagger/param_description/description.rb +15 -0
- data/lib/apipie/generator/swagger/param_description/in.rb +37 -0
- data/lib/apipie/generator/swagger/param_description/name.rb +18 -0
- data/lib/apipie/generator/swagger/param_description/path_params_composite.rb +61 -0
- data/lib/apipie/generator/swagger/param_description/referenced_composite.rb +36 -0
- data/lib/apipie/generator/swagger/param_description/type.rb +132 -0
- data/lib/apipie/generator/swagger/param_description.rb +18 -0
- data/lib/apipie/generator/swagger/path_decorator.rb +36 -0
- data/lib/apipie/generator/swagger/referenced_definitions.rb +17 -0
- data/lib/apipie/generator/swagger/resource_description_collection.rb +30 -0
- data/lib/apipie/generator/swagger/resource_description_composite.rb +56 -0
- data/lib/apipie/generator/swagger/schema.rb +63 -0
- data/lib/apipie/generator/swagger/swagger.rb +2 -0
- data/lib/apipie/generator/swagger/type.rb +16 -0
- data/lib/apipie/generator/swagger/type_extractor.rb +51 -0
- data/lib/apipie/generator/swagger/warning.rb +74 -0
- data/lib/apipie/generator/swagger/warning_writer.rb +54 -0
- data/lib/apipie/helpers.rb +73 -0
- data/lib/apipie/markup.rb +52 -0
- data/lib/apipie/method_description/api.rb +12 -0
- data/lib/apipie/method_description/apis_service.rb +82 -0
- data/lib/apipie/method_description.rb +230 -0
- data/lib/apipie/middleware/checksum_in_headers.rb +35 -0
- data/lib/apipie/param_description/deprecation.rb +24 -0
- data/lib/apipie/param_description.rb +313 -0
- data/lib/apipie/railtie.rb +9 -0
- data/lib/apipie/resource_description.rb +152 -0
- data/lib/apipie/response_description.rb +157 -0
- data/lib/apipie/response_description_adapter.rb +202 -0
- data/lib/apipie/routes_formatter.rb +33 -0
- data/lib/apipie/routing.rb +16 -0
- data/lib/apipie/rspec/response_validation_helper.rb +194 -0
- data/lib/apipie/see_description.rb +39 -0
- data/lib/apipie/static_dispatcher.rb +75 -0
- data/lib/apipie/swagger_generator.rb +45 -0
- data/lib/apipie/tag_list_description.rb +11 -0
- data/lib/apipie/validator.rb +552 -0
- data/lib/apipie/version.rb +3 -0
- data/lib/apipie-rails.rb +60 -0
- data/lib/generators/apipie/install/README +6 -0
- data/lib/generators/apipie/install/install_generator.rb +25 -0
- data/lib/generators/apipie/install/templates/initializer.rb.erb +7 -0
- data/lib/generators/apipie/views_generator.rb +11 -0
- data/lib/tasks/apipie.rake +355 -0
- data/rel-eng/gem_release.ipynb +398 -0
- data/rel-eng/packages/.readme +3 -0
- data/rel-eng/packages/rubygem-apipie-rails +1 -0
- data/rel-eng/tito.props +5 -0
- data/spec/controllers/api/v1/architectures_controller_spec.rb +29 -0
- data/spec/controllers/api/v2/architectures_controller_spec.rb +19 -0
- data/spec/controllers/api/v2/empty_middle_controller_spec.rb +23 -0
- data/spec/controllers/api/v2/nested/resources_controller_spec.rb +27 -0
- data/spec/controllers/api/v2/sub/footguns_controller_spec.rb +19 -0
- data/spec/controllers/concerns_controller_spec.rb +42 -0
- data/spec/controllers/extended_controller_spec.rb +14 -0
- data/spec/controllers/included_param_group_controller_spec.rb +13 -0
- data/spec/controllers/pets_controller_spec.rb +98 -0
- data/spec/controllers/users_controller_spec.rb +794 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/controllers/api/base_controller.rb +4 -0
- data/spec/dummy/app/controllers/api/v1/architectures_controller.rb +43 -0
- data/spec/dummy/app/controllers/api/v1/base_controller.rb +11 -0
- data/spec/dummy/app/controllers/api/v2/architectures_controller.rb +31 -0
- data/spec/dummy/app/controllers/api/v2/base_controller.rb +17 -0
- data/spec/dummy/app/controllers/api/v2/empty_middle_controller.rb +14 -0
- data/spec/dummy/app/controllers/api/v2/nested/architectures_controller.rb +32 -0
- data/spec/dummy/app/controllers/api/v2/nested/resources_controller.rb +33 -0
- data/spec/dummy/app/controllers/api/v2/sub/footguns_controller.rb +30 -0
- data/spec/dummy/app/controllers/application_controller.rb +18 -0
- data/spec/dummy/app/controllers/concerns_controller.rb +8 -0
- data/spec/dummy/app/controllers/extended_controller.rb +14 -0
- data/spec/dummy/app/controllers/extending_concern.rb +10 -0
- data/spec/dummy/app/controllers/files_controller.rb +5 -0
- data/spec/dummy/app/controllers/included_param_group_controller.rb +19 -0
- data/spec/dummy/app/controllers/overridden_concerns_controller.rb +31 -0
- data/spec/dummy/app/controllers/pets_controller.rb +408 -0
- data/spec/dummy/app/controllers/pets_using_auto_views_controller.rb +73 -0
- data/spec/dummy/app/controllers/pets_using_self_describing_classes_controller.rb +95 -0
- data/spec/dummy/app/controllers/sample_controller.rb +39 -0
- data/spec/dummy/app/controllers/tagged_cats_controller.rb +32 -0
- data/spec/dummy/app/controllers/tagged_dogs_controller.rb +15 -0
- data/spec/dummy/app/controllers/twitter_example_controller.rb +307 -0
- data/spec/dummy/app/controllers/users_controller.rb +310 -0
- data/spec/dummy/app/helpers/random_param_group.rb +8 -0
- data/spec/dummy/app/views/layouts/application.html.erb +21 -0
- data/spec/dummy/components/test_engine/Gemfile +6 -0
- data/spec/dummy/components/test_engine/app/controllers/test_engine/application_controller.rb +4 -0
- data/spec/dummy/components/test_engine/app/controllers/test_engine/memes_controller.rb +37 -0
- data/spec/dummy/components/test_engine/config/routes.rb +3 -0
- data/spec/dummy/components/test_engine/db/.gitkeep +0 -0
- data/spec/dummy/components/test_engine/lib/test_engine.rb +7 -0
- data/spec/dummy/components/test_engine/test_engine.gemspec +11 -0
- data/spec/dummy/config/application.rb +47 -0
- data/spec/dummy/config/boot.rb +12 -0
- data/spec/dummy/config/database.yml +21 -0
- data/spec/dummy/config/environment.rb +8 -0
- data/spec/dummy/config/environments/development.rb +25 -0
- data/spec/dummy/config/environments/production.rb +49 -0
- data/spec/dummy/config/environments/test.rb +33 -0
- data/spec/dummy/config/initializers/apipie.rb +110 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +10 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +8 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +61 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/db/.gitkeep +0 -0
- data/spec/dummy/doc/apipie_examples.json +1 -0
- data/spec/dummy/doc/users/desc_from_file.md +1 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +26 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/public/stylesheets/.gitkeep +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/lib/apipie/apipies_controller_spec.rb +345 -0
- data/spec/lib/apipie/application_spec.rb +62 -0
- data/spec/lib/apipie/configuration_spec.rb +38 -0
- data/spec/lib/apipie/extractor/collector_spec.rb +57 -0
- data/spec/lib/apipie/extractor/recorder/middleware_spec.rb +44 -0
- data/spec/lib/apipie/extractor/recorder_spec.rb +77 -0
- data/spec/lib/apipie/extractor/writer_spec.rb +112 -0
- data/spec/lib/apipie/extractor_spec.rb +9 -0
- data/spec/lib/apipie/file_handler_spec.rb +25 -0
- data/spec/lib/apipie/generator/swagger/config_spec.rb +19 -0
- data/spec/lib/apipie/generator/swagger/context_spec.rb +56 -0
- data/spec/lib/apipie/generator/swagger/method_description/api_schema_service_spec.rb +119 -0
- data/spec/lib/apipie/generator/swagger/method_description/response_schema_service_spec.rb +105 -0
- data/spec/lib/apipie/generator/swagger/method_description/response_service_spec.rb +62 -0
- data/spec/lib/apipie/generator/swagger/operation_id_spec.rb +63 -0
- data/spec/lib/apipie/generator/swagger/param_description/builder_spec.rb +245 -0
- data/spec/lib/apipie/generator/swagger/param_description/composite_spec.rb +95 -0
- data/spec/lib/apipie/generator/swagger/param_description/description_spec.rb +79 -0
- data/spec/lib/apipie/generator/swagger/param_description/in_spec.rb +86 -0
- data/spec/lib/apipie/generator/swagger/param_description/name_spec.rb +81 -0
- data/spec/lib/apipie/generator/swagger/param_description/type_spec.rb +210 -0
- data/spec/lib/apipie/generator/swagger/param_description_spec.rb +28 -0
- data/spec/lib/apipie/generator/swagger/path_decorator_spec.rb +57 -0
- data/spec/lib/apipie/generator/swagger/referenced_definitions_spec.rb +35 -0
- data/spec/lib/apipie/generator/swagger/resource_description_composite_spec.rb +37 -0
- data/spec/lib/apipie/generator/swagger/resource_descriptions_collection_spec.rb +57 -0
- data/spec/lib/apipie/generator/swagger/schema_spec.rb +89 -0
- data/spec/lib/apipie/generator/swagger/type_extractor_spec.rb +38 -0
- data/spec/lib/apipie/generator/swagger/warning_spec.rb +51 -0
- data/spec/lib/apipie/generator/swagger/warning_writer_spec.rb +71 -0
- data/spec/lib/apipie/method_description/apis_service_spec.rb +60 -0
- data/spec/lib/apipie/method_description_spec.rb +133 -0
- data/spec/lib/apipie/no_documented_method_spec.rb +17 -0
- data/spec/lib/apipie/param_description/deprecation_spec.rb +31 -0
- data/spec/lib/apipie/param_description_spec.rb +671 -0
- data/spec/lib/apipie/param_group_spec.rb +61 -0
- data/spec/lib/apipie/resource_description_spec.rb +91 -0
- data/spec/lib/apipie/response_description/response_object_spec.rb +22 -0
- data/spec/lib/apipie/response_description_spec.rb +56 -0
- data/spec/lib/apipie/response_does_not_match_swagger_schema_spec.rb +35 -0
- data/spec/lib/apipie/swagger_generator_spec.rb +94 -0
- data/spec/lib/apipie/validator_spec.rb +149 -0
- data/spec/lib/rake_spec.rb +69 -0
- data/spec/lib/swagger/openapi_2_0_schema.json +1614 -0
- data/spec/lib/swagger/rake_swagger_spec.rb +159 -0
- data/spec/lib/swagger/swagger_dsl_spec.rb +664 -0
- data/spec/lib/validators/array_validator_spec.rb +85 -0
- data/spec/spec_helper.rb +92 -0
- data/spec/support/custom_bool_validator.rb +17 -0
- data/spec/support/rake.rb +21 -0
- data/spec/test_engine/memes_controller_spec.rb +10 -0
- metadata +499 -0
@@ -0,0 +1,202 @@
|
|
1
|
+
module Apipie
|
2
|
+
|
3
|
+
def self.prop(name, expected_type, options = {}, sub_properties = [])
|
4
|
+
Apipie::ResponseDescriptionAdapter::PropDesc.new(name, expected_type, options, sub_properties)
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.additional_properties(yesno)
|
8
|
+
Apipie::ResponseDescriptionAdapter::AdditionalPropertiesModifier.new(yesno)
|
9
|
+
end
|
10
|
+
|
11
|
+
class ResponseDescriptionAdapter
|
12
|
+
class Modifier
|
13
|
+
def apply(adapter)
|
14
|
+
raise "Modifier subclass must implement 'apply' method"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class AdditionalPropertiesModifier < Modifier
|
19
|
+
def initialize(additional_properties_allowed)
|
20
|
+
@additional_properties_allowed = additional_properties_allowed
|
21
|
+
end
|
22
|
+
|
23
|
+
def apply(adapter)
|
24
|
+
adapter.additional_properties = @additional_properties_allowed
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
class ResponseDescriptionAdapter
|
31
|
+
|
32
|
+
#
|
33
|
+
# A ResponseDescriptionAdapter::PropDesc object pretends to be an Apipie::Param in a ResponseDescription
|
34
|
+
#
|
35
|
+
# To successfully masquerade as such, it needs to:
|
36
|
+
# respond_to?('name') and/or ['name'] returning the name of the parameter
|
37
|
+
# respond_to?('required') and/or ['required'] returning boolean
|
38
|
+
# respond_to?('additional_properties') and/or ['additional_properties'] returning boolean
|
39
|
+
# respond_to?('validator') and/or ['validator'] returning 'nil' (so type is 'string'), or an object that:
|
40
|
+
# 1) describes a type. currently type is inferred as follows:
|
41
|
+
# if validator.is_a? Apipie::Validator::EnumValidator --> respond_to? 'values' (returns array). Type is enum or boolean
|
42
|
+
# else: use v.expected_type(). This is expected to be the swagger type, or:
|
43
|
+
# numeric ==> swagger type is 'number'
|
44
|
+
# hash ==> swagger type is 'object' and validator should respond_to? 'params_ordered'
|
45
|
+
# array ==> swagger type is array and validator (FUTURE) should indicate type of element
|
46
|
+
|
47
|
+
class PropDesc
|
48
|
+
|
49
|
+
def to_s
|
50
|
+
"PropDesc -- name: #{@name} type: #{@expected_type} required: #{@required} options: #{@options} subprop count: #{@sub_properties.length} additional properties: #{@additional_properties}"
|
51
|
+
end
|
52
|
+
|
53
|
+
#
|
54
|
+
# a ResponseDescriptionAdapter::PropDesc::Validator pretends to be an Apipie::Validator
|
55
|
+
#
|
56
|
+
class Validator
|
57
|
+
attr_reader :expected_type
|
58
|
+
|
59
|
+
def [](key)
|
60
|
+
self.send(key) if self.respond_to?(key.to_s)
|
61
|
+
end
|
62
|
+
|
63
|
+
def initialize(expected_type, enum_values = nil, sub_properties = nil)
|
64
|
+
@expected_type = expected_type
|
65
|
+
@enum_values = enum_values
|
66
|
+
@is_enum = !!enum_values
|
67
|
+
@sub_properties = sub_properties
|
68
|
+
end
|
69
|
+
|
70
|
+
def is_enum?
|
71
|
+
!!@is_enum
|
72
|
+
end
|
73
|
+
|
74
|
+
def values
|
75
|
+
@enum_values
|
76
|
+
end
|
77
|
+
|
78
|
+
def params_ordered
|
79
|
+
raise "Only validators with expected_type 'object' can have sub-properties" unless @expected_type == 'object'
|
80
|
+
@sub_properties
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
#======================================================================
|
85
|
+
|
86
|
+
|
87
|
+
def initialize(name, expected_type, options = {}, sub_properties = [])
|
88
|
+
@name = name
|
89
|
+
@required = true
|
90
|
+
@required = false if options[:required] == false
|
91
|
+
@expected_type = expected_type
|
92
|
+
@additional_properties = false
|
93
|
+
|
94
|
+
options[:desc] ||= options[:description]
|
95
|
+
@description = options[:desc]
|
96
|
+
@options = options
|
97
|
+
@is_array = options[:is_array] || false
|
98
|
+
@sub_properties = []
|
99
|
+
for prop in sub_properties do
|
100
|
+
add_sub_property(prop)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def [](key)
|
105
|
+
self.send(key) if self.respond_to?(key.to_s)
|
106
|
+
end
|
107
|
+
|
108
|
+
def add_sub_property(prop_desc)
|
109
|
+
raise "Only properties with expected_type 'object' can have sub-properties" unless @expected_type == 'object'
|
110
|
+
case prop_desc
|
111
|
+
when PropDesc
|
112
|
+
@sub_properties << prop_desc
|
113
|
+
when Modifier
|
114
|
+
prop_desc.apply(self)
|
115
|
+
else
|
116
|
+
raise "Unrecognized prop_desc type (#{prop_desc.class})"
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def to_json(lang)
|
121
|
+
{
|
122
|
+
name: name,
|
123
|
+
required: required,
|
124
|
+
validator: validator,
|
125
|
+
description: description,
|
126
|
+
additional_properties: additional_properties,
|
127
|
+
is_array: is_array?,
|
128
|
+
options: options
|
129
|
+
}
|
130
|
+
end
|
131
|
+
attr_reader :name, :required, :expected_type, :options, :description
|
132
|
+
attr_accessor :additional_properties
|
133
|
+
|
134
|
+
alias desc description
|
135
|
+
|
136
|
+
def is_array?
|
137
|
+
@is_array
|
138
|
+
end
|
139
|
+
|
140
|
+
def validator
|
141
|
+
Validator.new(@expected_type, options[:values], @sub_properties)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
#======================================================================
|
147
|
+
|
148
|
+
class ResponseDescriptionAdapter
|
149
|
+
|
150
|
+
def self.from_self_describing_class(cls)
|
151
|
+
adapter = ResponseDescriptionAdapter.new(cls.to_s)
|
152
|
+
props = cls.describe_own_properties
|
153
|
+
adapter.add_property_descriptions(props)
|
154
|
+
adapter
|
155
|
+
end
|
156
|
+
|
157
|
+
def initialize(typename)
|
158
|
+
@property_descs = []
|
159
|
+
@additional_properties = false
|
160
|
+
@typename = typename
|
161
|
+
end
|
162
|
+
|
163
|
+
attr_accessor :additional_properties, :typename
|
164
|
+
|
165
|
+
def allow_additional_properties
|
166
|
+
additional_properties
|
167
|
+
end
|
168
|
+
|
169
|
+
def to_json
|
170
|
+
params_ordered.to_json
|
171
|
+
end
|
172
|
+
|
173
|
+
def add(prop_desc)
|
174
|
+
case prop_desc
|
175
|
+
when PropDesc
|
176
|
+
@property_descs << prop_desc
|
177
|
+
when Modifier
|
178
|
+
prop_desc.apply(self)
|
179
|
+
else
|
180
|
+
raise "Unrecognized prop_desc type (#{prop_desc.class})"
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
def add_property_descriptions(prop_descs)
|
185
|
+
for prop_desc in prop_descs
|
186
|
+
add(prop_desc)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def property(name, expected_type, options)
|
191
|
+
@property_descs << PropDesc.new(name, expected_type, options)
|
192
|
+
end
|
193
|
+
|
194
|
+
def params_ordered
|
195
|
+
@property_descs
|
196
|
+
end
|
197
|
+
|
198
|
+
def is_array?
|
199
|
+
false
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Apipie
|
2
|
+
class RoutesFormatter
|
3
|
+
API_METHODS = %w{GET POST PUT PATCH OPTIONS DELETE}.freeze
|
4
|
+
|
5
|
+
# The entry method called by Apipie to extract the array
|
6
|
+
# representing the api dsl from the routes definition.
|
7
|
+
def format_routes(rails_routes, args)
|
8
|
+
rails_routes.map { |rails_route| format_route(rails_route, args) }
|
9
|
+
end
|
10
|
+
|
11
|
+
def format_route(rails_route, args)
|
12
|
+
{ :path => format_path(rails_route),
|
13
|
+
:verb => format_verb(rails_route),
|
14
|
+
:desc => args[:desc],
|
15
|
+
:options => args[:options] }
|
16
|
+
end
|
17
|
+
|
18
|
+
def format_path(rails_route)
|
19
|
+
File.join(rails_route.base_url, rails_route.path.spec.to_s.gsub('(.:format)', ''))
|
20
|
+
end
|
21
|
+
|
22
|
+
def format_verb(rails_route)
|
23
|
+
verb = API_METHODS.select{|defined_verb| defined_verb =~ /\A#{rails_route.verb}\z/}
|
24
|
+
if verb.count != 1
|
25
|
+
verb = API_METHODS.select{|defined_verb| defined_verb == rails_route.constraints[:method]}
|
26
|
+
if verb.blank?
|
27
|
+
raise "Unknown verb #{rails_route.path.spec.to_s}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
verb.first
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Apipie
|
2
|
+
module Routing
|
3
|
+
module MapperExtensions
|
4
|
+
def apipie(options = {})
|
5
|
+
namespace "apipie", :path => Apipie.configuration.doc_base_url do
|
6
|
+
get 'apipie_checksum', :to => "apipies#apipie_checksum", :format => "json"
|
7
|
+
constraints(:version => %r{[^/]+}, :resource => %r{[^/]+}, :method => %r{[^/]+}) do
|
8
|
+
get(options.reverse_merge("(:version)/(:resource)/(:method)" => "apipies#index", :as => :apipie))
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
ActionDispatch::Routing::Mapper.send :include, Apipie::Routing::MapperExtensions
|
@@ -0,0 +1,194 @@
|
|
1
|
+
#----------------------------------------------------------------------------------------------
|
2
|
+
# response_validation_helper.rb:
|
3
|
+
#
|
4
|
+
# this is an rspec utility to allow validation of responses against the swagger schema generated
|
5
|
+
# from the Apipie 'returns' definition for the call.
|
6
|
+
#
|
7
|
+
#
|
8
|
+
# to use this file in a controller rspec you should
|
9
|
+
# require 'apipie/rspec/response_validation_helper' in the spec file
|
10
|
+
#
|
11
|
+
#
|
12
|
+
# this utility provides two mechanisms: matcher-based validation and auto-validation
|
13
|
+
#
|
14
|
+
# matcher-based: an rspec matcher allowing 'expect(response).to match_declared_responses'
|
15
|
+
# auto-validation: all responses returned from 'get', 'post', etc. are automatically tested
|
16
|
+
#
|
17
|
+
# ===================================
|
18
|
+
# Matcher-based validation - example
|
19
|
+
# ===================================
|
20
|
+
# Assume the file 'my_controller_spec.rb':
|
21
|
+
#
|
22
|
+
# require 'apipie/rspec/response_validation_helper'
|
23
|
+
#
|
24
|
+
# RSpec.describe MyController, :type => :controller, :show_in_doc => true do
|
25
|
+
#
|
26
|
+
# describe "GET stuff with response validation" do
|
27
|
+
# render_views # this makes sure the 'get' operation will actually
|
28
|
+
# # return the rendered view even though this is a Controller spec
|
29
|
+
#
|
30
|
+
# it "does something" do
|
31
|
+
# response = get :index, {format: :json}
|
32
|
+
#
|
33
|
+
# # the following expectation will fail if the returned object
|
34
|
+
# # does not match the 'returns' declaration in the Controller,
|
35
|
+
# # or if there is no 'returns' declaration for the returned
|
36
|
+
# # HTTP status code
|
37
|
+
# expect(response).to match_declared_responses
|
38
|
+
# end
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
#
|
42
|
+
# ===================================
|
43
|
+
# Auto-validation
|
44
|
+
# ===================================
|
45
|
+
# To use auto-validation, at the beginning of the block in which you want to turn on validation:
|
46
|
+
# -) turn on view rendering (by stating 'render_views')
|
47
|
+
# -) turn on response validation by stating 'auto_validate_rendered_views'
|
48
|
+
#
|
49
|
+
# For example, assume the file 'my_controller_spec.rb':
|
50
|
+
#
|
51
|
+
# require 'apipie/rspec/response_validation_helper'
|
52
|
+
#
|
53
|
+
# RSpec.describe MyController, :type => :controller, :show_in_doc => true do
|
54
|
+
#
|
55
|
+
# describe "GET stuff with response validation" do
|
56
|
+
# render_views
|
57
|
+
# auto_validate_rendered_views
|
58
|
+
#
|
59
|
+
# it "does something" do
|
60
|
+
# get :index, {format: :json}
|
61
|
+
# end
|
62
|
+
# it "does something else" do
|
63
|
+
# get :another_index, {format: :json}
|
64
|
+
# end
|
65
|
+
# end
|
66
|
+
#
|
67
|
+
# describe "GET stuff without response validation" do
|
68
|
+
# it "does something" do
|
69
|
+
# get :index, {format: :json}
|
70
|
+
# end
|
71
|
+
# it "does something else" do
|
72
|
+
# get :another_index, {format: :json}
|
73
|
+
# end
|
74
|
+
# end
|
75
|
+
#
|
76
|
+
#
|
77
|
+
# Once this is done, responses from http operations ('get', 'post', 'delete', etc.)
|
78
|
+
# will fail the test if the response structure does not match the 'returns' declaration
|
79
|
+
# on the method (for the actual HTTP status code), or if there is no 'returns' declaration
|
80
|
+
# for the HTTP status code.
|
81
|
+
#----------------------------------------------------------------------------------------------
|
82
|
+
|
83
|
+
|
84
|
+
#----------------------------------------------------------------------------------------------
|
85
|
+
# Response validation: core logic (used by auto-validation and manual-validation mechanisms)
|
86
|
+
#----------------------------------------------------------------------------------------------
|
87
|
+
class ActionController::Base
|
88
|
+
module Apipie::ControllerValidationHelpers
|
89
|
+
# this method is injected into ActionController::Base in order to
|
90
|
+
# get access to the names of the current controller, current action, as well as to the response
|
91
|
+
def schema_validation_errors_for_response
|
92
|
+
unprocessed_schema = Apipie::json_schema_for_method_response(controller_name, action_name, response.code, true)
|
93
|
+
|
94
|
+
if unprocessed_schema.nil?
|
95
|
+
err = "no schema defined for #{controller_name}##{action_name}[#{response.code}]"
|
96
|
+
return [nil, [err], RuntimeError.new(err)]
|
97
|
+
end
|
98
|
+
|
99
|
+
schema = JSON.parse(JSON(unprocessed_schema))
|
100
|
+
|
101
|
+
error_list = JSON::Validator.fully_validate(schema, response.body, :strict => false, :version => :draft4, :json => true)
|
102
|
+
|
103
|
+
error_object = Apipie::ResponseDoesNotMatchSwaggerSchema.new(controller_name, action_name, response.code, error_list, schema, response.body)
|
104
|
+
|
105
|
+
[schema, error_list, error_object]
|
106
|
+
rescue Apipie::NoDocumentedMethod
|
107
|
+
[nil, [], nil]
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
include Apipie::ControllerValidationHelpers
|
112
|
+
end
|
113
|
+
|
114
|
+
module Apipie
|
115
|
+
def self.print_validation_errors(validation_errors, schema, response, error_object = nil)
|
116
|
+
Rails.logger.warn(validation_errors.to_s)
|
117
|
+
if Rails.env.test?
|
118
|
+
puts "schema validation errors:"
|
119
|
+
validation_errors.each { |e| puts "--> #{e.to_s}" }
|
120
|
+
puts "schema: #{schema.nil? ? '<none>' : JSON(schema)}"
|
121
|
+
puts "response: #{response.body}"
|
122
|
+
raise error_object if error_object
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
#---------------------------------
|
128
|
+
# Manual-validation (RSpec matcher)
|
129
|
+
#---------------------------------
|
130
|
+
RSpec::Matchers.define :match_declared_responses do
|
131
|
+
match do |actual|
|
132
|
+
(schema, validation_errors) = subject.send(:schema_validation_errors_for_response)
|
133
|
+
valid = (validation_errors == [])
|
134
|
+
Apipie::print_validation_errors(validation_errors, schema, response) unless valid
|
135
|
+
|
136
|
+
valid
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
|
141
|
+
#---------------------------------
|
142
|
+
# Auto-validation logic
|
143
|
+
#---------------------------------
|
144
|
+
module RSpec::Rails::ViewRendering
|
145
|
+
# Augment the RSpec DSL
|
146
|
+
module ClassMethods
|
147
|
+
def auto_validate_rendered_views
|
148
|
+
before do
|
149
|
+
@is_response_validation_on = true
|
150
|
+
end
|
151
|
+
|
152
|
+
after do
|
153
|
+
@is_response_validation_on = false
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
|
160
|
+
ActionController::TestCase::Behavior.instance_eval do
|
161
|
+
# instrument the 'process' method in ActionController::TestCase to enable response validation
|
162
|
+
module Apipie::ResponseValidationHelpers
|
163
|
+
@is_response_validation_on = false
|
164
|
+
def process(*, **)
|
165
|
+
result = super
|
166
|
+
validate_response if @is_response_validation_on
|
167
|
+
|
168
|
+
result
|
169
|
+
end
|
170
|
+
|
171
|
+
def validate_response
|
172
|
+
controller.send(:validate_response_and_abort_with_info_if_errors)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
prepend Apipie::ResponseValidationHelpers
|
177
|
+
end
|
178
|
+
|
179
|
+
|
180
|
+
class ActionController::Base
|
181
|
+
module Apipie::ControllerValidationHelpers
|
182
|
+
def validate_response_and_abort_with_info_if_errors
|
183
|
+
|
184
|
+
(schema, validation_errors, error_object) = schema_validation_errors_for_response
|
185
|
+
|
186
|
+
valid = (validation_errors == [])
|
187
|
+
if !valid
|
188
|
+
Apipie::print_validation_errors(validation_errors, schema, response, error_object)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Apipie
|
2
|
+
|
3
|
+
class SeeDescription
|
4
|
+
|
5
|
+
attr_reader :link, :description
|
6
|
+
|
7
|
+
def initialize(args)
|
8
|
+
if args.first.is_a? Hash
|
9
|
+
args = args.first
|
10
|
+
elsif args.count == 2
|
11
|
+
if args.last.is_a? Hash
|
12
|
+
args = {:link => args.first}.merge(args.last)
|
13
|
+
else
|
14
|
+
args = {:link => args.first, :description => args.second}
|
15
|
+
end
|
16
|
+
elsif args.count == 1 && args.first.is_a?(String)
|
17
|
+
args = {:link => args.first, :description => args.first}
|
18
|
+
else
|
19
|
+
raise ArgumentError "ApipieError: Bad use of see method."
|
20
|
+
end
|
21
|
+
@link = args[:link] || args['link']
|
22
|
+
@description = args[:desc] || args[:description] || args['desc'] || args['description']
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_json
|
26
|
+
{:link => see_url, :description => description}
|
27
|
+
end
|
28
|
+
|
29
|
+
def see_url
|
30
|
+
method_description = Apipie[@link]
|
31
|
+
if method_description.nil?
|
32
|
+
raise ArgumentError.new("Method #{@link} referenced in 'see' does not exist.")
|
33
|
+
end
|
34
|
+
method_description.doc_url
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module Apipie
|
2
|
+
|
3
|
+
class FileHandler
|
4
|
+
def initialize(root)
|
5
|
+
@root = root.chomp('/')
|
6
|
+
@compiled_root = /^#{Regexp.escape(root)}/
|
7
|
+
@file_server = if defined?(::Rack::Files)
|
8
|
+
::Rack::Files.new(@root)
|
9
|
+
else
|
10
|
+
# Deprecated in Rack 3.0, kept
|
11
|
+
# for backward compatibility
|
12
|
+
::Rack::File.new(@root)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def match?(path)
|
17
|
+
# Replace all null bytes
|
18
|
+
path = ::Rack::Utils.unescape(path || '')
|
19
|
+
.encode(Encoding::UTF_8, invalid: :replace, replace: '')
|
20
|
+
.gsub("\x0", '')
|
21
|
+
|
22
|
+
full_path = path.empty? ? @root : File.join(@root, path)
|
23
|
+
paths = "#{full_path}#{ext}"
|
24
|
+
|
25
|
+
matches = Dir[paths]
|
26
|
+
match = matches.detect { |m| File.file?(m) }
|
27
|
+
if match
|
28
|
+
match.sub!(@compiled_root, '')
|
29
|
+
match
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
delegate :call, to: :@file_server
|
34
|
+
|
35
|
+
def ext
|
36
|
+
@ext ||= begin
|
37
|
+
ext = cache_extension
|
38
|
+
"{,#{ext},/index#{ext}}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def cache_extension
|
43
|
+
if ::ActionController::Base.respond_to?(:default_static_extension)
|
44
|
+
::ActionController::Base.default_static_extension
|
45
|
+
else
|
46
|
+
::ActionController::Base.page_cache_extension
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class StaticDispatcher
|
53
|
+
# Dispatches the static files. Similar to ActionDispatch::Static, but
|
54
|
+
# it supports different baseurl configurations
|
55
|
+
def initialize(app, path)
|
56
|
+
@app = app
|
57
|
+
@file_handler = Apipie::FileHandler.new(path)
|
58
|
+
end
|
59
|
+
|
60
|
+
def call(env)
|
61
|
+
@baseurl ||= Apipie.configuration.doc_base_url
|
62
|
+
case env['REQUEST_METHOD']
|
63
|
+
when 'GET', 'HEAD'
|
64
|
+
path = env['PATH_INFO'].sub("#{@baseurl}/","/apipie/").chomp('/')
|
65
|
+
|
66
|
+
if match = @file_handler.match?(path)
|
67
|
+
env["PATH_INFO"] = match
|
68
|
+
return @file_handler.call(env)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
@app.call(env)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Apipie
|
2
|
+
class SwaggerGenerator
|
3
|
+
# @param [Array<Apipie::ResourceDescription] resources
|
4
|
+
def self.generate_from_resources(resources, version:, language:, clear_warnings: false)
|
5
|
+
Apipie::Generator::Swagger::Schema.new(
|
6
|
+
resources,
|
7
|
+
version: version,
|
8
|
+
language: language,
|
9
|
+
clear_warnings: clear_warnings
|
10
|
+
).generate
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.json_schema_for_method_response(method, return_code, allow_nulls)
|
14
|
+
response = method.returns.find { |response| response.code.to_s == return_code.to_s }
|
15
|
+
|
16
|
+
return if response.blank?
|
17
|
+
|
18
|
+
http_method = method.apis.first.http_method
|
19
|
+
|
20
|
+
schema = Apipie::Generator::Swagger::MethodDescription::ResponseSchemaService.new(
|
21
|
+
response,
|
22
|
+
allow_null: allow_nulls,
|
23
|
+
http_method: http_method,
|
24
|
+
controller_method: method
|
25
|
+
).to_swagger
|
26
|
+
|
27
|
+
definitions = Apipie::Generator::Swagger::ReferencedDefinitions.instance.definitions
|
28
|
+
|
29
|
+
if definitions.present?
|
30
|
+
schema[:definitions] = definitions
|
31
|
+
end
|
32
|
+
|
33
|
+
schema
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.json_schema_for_self_describing_class(cls, allow_nulls)
|
37
|
+
Apipie::Generator::Swagger::MethodDescription::ResponseSchemaService.new(
|
38
|
+
ResponseDescriptionAdapter.from_self_describing_class(cls),
|
39
|
+
allow_null: allow_nulls,
|
40
|
+
http_method: nil,
|
41
|
+
controller_method: nil
|
42
|
+
).to_swagger
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|