Skip to content

Commit

Permalink
Added Swagger generation
Browse files Browse the repository at this point in the history
  • Loading branch information
elasti-ron authored and iNecas committed Dec 11, 2017
1 parent b272aae commit 75a16bd
Show file tree
Hide file tree
Showing 14 changed files with 2,581 additions and 3 deletions.
105 changes: 105 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1154,6 +1154,111 @@ If, for some complex cases, you need to generate/re-generate just part of the ca
use ``rake apipie:cache cache_part=index`` resp. ``rake apipie:cache cache_part=resources``
To generate it for different locations for further processing use ``rake apipie:cache OUT=/tmp/apipie_cache``.

====================================
Static Swagger (OpenAPI 2.0) files
====================================

To generate a static Swagger definition file from the api, run ``rake apipie:static_swagger_json``.
By default the documentation for the default API version is
used. You can specify the version with ``rake apipie:static_swagger_json[2.0]``. A swagger file will be
generated for each locale. The files will be generated in the same location as the static_json files, but
instead of being named ``schema_apipie[.locale].json``, they will be called ``schema_swagger[.locale].json``.

Specifying default values for parameters
-----------------------------------------
Swagger allows method definitions to include an indication of the the default value for each parameter. To include such
indications, use ``:default_value => <some value>`` in the parameter definition DSL. For example:

.. code:: ruby
param :do_something, Boolean, :desc => "take an action", :required => false, :default_value => false
Generated Warnings
-------------------
The help identify potential improvements to your documentation, the swagger generation process issues warnings if
it identifies various shortcomings of the DSL documentation. Each warning has a code to allow selective suppression
(see swagger-specific configuration below)

:100: missing short description for method
:101: added missing / at beginning of path
:102: no return codes specified for method
:103: a parameter is a generic Hash without an internal type specification
:104: a parameter is an 'in-path' parameter, but specified as 'not required' in the DSL
:105: a parameter is optional but does not have a default value specified
:106: a parameter was ommitted from the swagger output because it is a Hash without fields in a formData specification
:107: a path parameter is not described
:108: inferring that a parameter type is boolean because described as an enum with [false,true] values



Swagger-Specific Configuration Parameters
-------------------------------------------------

There are several configuration parameters that determine the structure of the generated swagger file:

``config.swagger_content_type_input``
If the value is ``:form_data`` - the swagger file will indicate that the server consumes the content types
``application/x-www-form-urlencoded`` and ``multipart/form-data``. Non-path parameters will have the
value ``"in": "formData"``. Note that parameters of type Hash that do not have any fields in them will *be ommitted*
from the resulting files, as there is no way to describe them in swagger.

If the value is ``:json`` - the swagger file will indicate that the server consumes the content type
``application/json``. All non-path parameters will be included in the schema of a single ``"in": "body"`` parameter
of type ``object``.

You can specify the value of this configuration parameter as an additional input to the rake command (e.g.,
``rake apipie:static_swagger_json[2.0,form_data]``).

``config.swagger_json_input_uses_refs``
This parameter is only relevant if ``swagger_content_type_input`` is ``:json``.

If ``true``: the schema of the ``"in": "body"`` parameter of each method is given its own entry in the ``definitions``
section, and is referenced using ``$ref`` from the method definition.

If ``false``: the body parameter definitions are inlined within the method definitions.

``config.swagger_include_warning_tags``
If ``true``: in addition to tagging methods with the name of the resource they belong to, methods for which warnings
have been issued will be tagged with.

``config.swagger_suppress_warnings``
If ``false``: no warnings will be suppressed

If ``true``: all warnings will be suppressed

If an array of values (e.g., ``[100,102,107]``), only the warnings identified by the numbers in the array will be suppressed.

``config.swagger_api_host``
The value to place in the swagger host field.

Default is ``localhost:3000``

If ``nil`` then then host field will not be included.



Known limitations of the current implementation
-------------------------------------------------
* There is currently no way to document the structure and content-type of the data returned from a method
* Recorded examples are currently not included in the generated swagger file
* The apipie ``formats`` value is ignored.
* It is not possible to specify the "consumed" content type on a per-method basis
* It is not possible to leverage all of the parameter type/format capabilities of swagger
* Only OpenAPI 2.0 is supported

====================================
Dynamic Swagger generation
====================================

To generate swagger dynamically, use ``http://localhost:3000/apipie.json?type=swagger``.

Note that authorization is not supported for dynamic swagger generation, so if ``config.authorize`` is defined,
dynamic swagger generation will be disabled.

Dynamically generated swagger is not cached, and is always generated on the fly.


===================
JSON checksums
===================
Expand Down
1 change: 1 addition & 0 deletions apipie-rails.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@ Gem::Specification.new do |s|
s.add_development_dependency "RedCloth"
s.add_development_dependency "rake"
s.add_development_dependency "rdoc"
s.add_development_dependency "json-schema", "~> 2.8"
end
20 changes: 18 additions & 2 deletions app/controllers/apipie/apipies_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,17 @@ def authenticate
end
end


def index
params[:version] ||= Apipie.configuration.default_version

get_format

if params[:type].to_s == 'swagger' && params[:format].to_s == 'json'
head :forbidden and return if Apipie.configuration.authorize
should_render_swagger = true
end

respond_to do |format|

if Apipie.configuration.use_cache?
Expand All @@ -31,9 +37,19 @@ def index
Apipie.load_documentation if Apipie.configuration.reload_controllers? || (Rails.version.to_i >= 4.0 && !Rails.application.config.eager_load)

I18n.locale = @language
@doc = Apipie.to_json(params[:version], params[:resource], params[:method], @language)

@doc = authorized_doc
if should_render_swagger
prev_warning_value = Apipie.configuration.swagger_suppress_warnings
begin
Apipie.configuration.swagger_suppress_warnings = true
@doc = Apipie.to_swagger_json(params[:version], params[:resource], params[:method], @language)
ensure
Apipie.configuration.swagger_suppress_warnings = prev_warning_value
end
else
@doc = Apipie.to_json(params[:version], params[:resource], params[:method], @language)
@doc = authorized_doc
end

format.json do
if @doc
Expand Down
1 change: 1 addition & 0 deletions lib/apipie-rails.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
require "apipie/railtie"
require 'apipie/extractor'
require "apipie/version"
require "apipie/swagger_generator"

if Rails.version.start_with?("3.0")
warn 'Warning: apipie-rails is not going to support Rails 3.0 anymore in future versions'
Expand Down
5 changes: 5 additions & 0 deletions lib/apipie/apipie_module.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ def self.to_json(version = nil, resource_name = nil, method_name = nil, lang = n
app.to_json(version, resource_name, method_name, lang)
end

def self.to_swagger_json(version = nil, resource_name = nil, method_name = nil, lang = nil, clear_warnings=true)
version ||= Apipie.configuration.default_version
app.to_swagger_json(version, resource_name, method_name, lang, clear_warnings)
end

# all calls delegated to Apipie::Application instance
def self.method_missing(method, *args, &block)
app.respond_to?(method) ? app.send(method, *args, &block) : super
Expand Down
19 changes: 19 additions & 0 deletions lib/apipie/application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ def init_env
@resource_descriptions ||= HashWithIndifferentAccess.new { |h, version| h[version] = {} }
@controller_to_resource_id ||= {}
@param_groups ||= {}
@swagger_generator = Apipie::SwaggerGenerator.new(self)

# what versions does the controller belong in (specified by resource_description)?
@controller_versions ||= Hash.new { |h, controller| h[controller.to_s] = [] }
Expand All @@ -254,6 +255,24 @@ def reload_examples
@recorded_examples = nil
end

def to_swagger_json(version, resource_name, method_name, lang, clear_warnings=false)
return unless valid_search_args?(version, resource_name, method_name)

# if resource_name is blank, take just resources which have some methods because
# we dont want to show eg ApplicationController as resource
# otherwise, take only the specified resource
_resources = resource_descriptions[version].inject({}) do |result, (k,v)|
if resource_name.blank?
result[k] = v unless v._methods.blank?
else
result[k] = v if k == resource_name
end
result
end

@swagger_generator.generate_from_resources(version,_resources, method_name, lang, clear_warnings)
end

def to_json(version, resource_name, method_name, lang)

return unless valid_search_args?(version, resource_name, method_name)
Expand Down
13 changes: 12 additions & 1 deletion lib/apipie/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,16 @@ class Configuration
:validate, :validate_value, :validate_presence, :validate_key, :authenticate, :doc_path,
:show_all_examples, :process_params, :update_checksum, :checksum_path,
:link_extension, :record, :languages, :translate, :locale, :default_locale,
:persist_show_in_doc, :authorize
:persist_show_in_doc, :authorize,
:swagger_include_warning_tags, :swagger_content_type_input, :swagger_json_input_uses_refs,
:swagger_suppress_warnings, :swagger_api_host, :swagger_generate_x_computed_id_field

alias_method :validate?, :validate
alias_method :required_by_default?, :required_by_default
alias_method :namespaced_resources?, :namespaced_resources
alias_method :swagger_include_warning_tags?, :swagger_include_warning_tags
alias_method :swagger_json_input_uses_refs?, :swagger_json_input_uses_refs
alias_method :swagger_generate_x_computed_id_field?, :swagger_generate_x_computed_id_field

# matcher to be used in Dir.glob to find controllers to be reloaded e.g.
#
Expand Down Expand Up @@ -165,6 +170,12 @@ def initialize
@translate = lambda { |str, locale| str }
@persist_show_in_doc = false
@routes_formatter = RoutesFormatter.new
@swagger_content_type_input = :form_data # this can be :json or :form_data
@swagger_json_input_uses_refs = false
@swagger_include_warning_tags = false
@swagger_suppress_warnings = false #[105,100,102]
@swagger_api_host = "localhost:3000"
@swagger_generate_x_computed_id_field = false
end
end
end
Loading

0 comments on commit 75a16bd

Please sign in to comment.