rename to rswag plus major refactor - almost a rewrite

This commit is contained in:
richie
2016-10-11 18:31:12 -07:00
parent f8d993356f
commit c558098c39
453 changed files with 52410 additions and 35793 deletions

2
rswag-api/.rspec Normal file
View File

@@ -0,0 +1,2 @@
--color
--require spec_helper

20
rswag-api/MIT-LICENSE Normal file
View File

@@ -0,0 +1,20 @@
Copyright 2015 domaindrivendev
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

27
rswag-api/Rakefile Normal file
View File

@@ -0,0 +1,27 @@
#!/usr/bin/env rake
begin
require 'bundler/setup'
rescue LoadError
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
end
begin
require 'rdoc/task'
rescue LoadError
require 'rdoc/rdoc'
require 'rake/rdoctask'
RDoc::Task = Rake::RDocTask
end
RDoc::Task.new(:rdoc) do |rdoc|
rdoc.rdoc_dir = 'rdoc'
rdoc.title = 'rswag-specs'
rdoc.options << '--line-numbers'
rdoc.rdoc_files.include('README.rdoc')
rdoc.rdoc_files.include('lib/**/*.rb')
end
Bundler::GemHelper.install_tasks

12
rswag-api/bin/rails Executable file
View File

@@ -0,0 +1,12 @@
#!/usr/bin/env ruby
# This command will automatically be run when you run "rails" with Rails 4 gems installed from the root of your application.
ENGINE_ROOT = File.expand_path('../..', __FILE__)
ENGINE_PATH = File.expand_path('../../lib/rswag/api/engine', __FILE__)
# Set up gems listed in the Gemfile.
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
require 'rails/all'
require 'rails/engine/commands'

View File

@@ -0,0 +1,8 @@
Description:
Adds rswag-api initializer for configuration
Example:
rails generate rswag:api:install
This will create:
config/initializers/rswag-api.rb

View File

@@ -0,0 +1,18 @@
require 'rails/generators'
module Rswag
module Api
class InstallGenerator < Rails::Generators::Base
source_root File.expand_path('../templates', __FILE__)
def add_initializer
template('rswag-api.rb', 'config/initializers/rswag-api.rb')
end
def add_routes
route("mount Rswag::Api::Engine => '/api-docs'")
end
end
end
end

View File

@@ -0,0 +1,14 @@
Rswag::Api.configure do |c|
# Specify a root folder where Swagger JSON files are located
# This is used by the Swagger middleware to serve requests for API descriptions
# NOTE: If you're using rswag-specs to generate Swagger, you'll need to ensure
# that it's configured to generate files in the same folder
c.swagger_root = Rails.root.to_s + '/swagger'
# Inject a lamda function to alter the returned Swagger prior to serialization
# The function will have access to the rack env for the current request
# For example, you could leverage this to dynamically assign the "host" property
#
#c.swagger_filter = lambda { |swagger, env| swagger['host'] = env['HTTP_HOST'] }
end

View File

@@ -0,0 +1,15 @@
require 'rswag/api/version'
require 'rswag/api/configuration'
require 'rswag/api/engine'
module Rswag
module Api
def self.configure
yield(config)
end
def self.config
@config ||= Configuration.new
end
end
end

View File

@@ -0,0 +1,12 @@
module Rswag
module Api
class Configuration
attr_accessor :swagger_root, :swagger_filter
def resolve_swagger_root(env)
path_params = env['action_dispatch.request.path_parameters'] || {}
path_params[:swagger_root] || swagger_root
end
end
end
end

View File

@@ -0,0 +1,13 @@
require 'rswag/api/middleware'
module Rswag
module Api
class Engine < ::Rails::Engine
isolate_namespace Rswag::Api
initializer 'rswag-api.initialize' do |app|
middleware.use Rswag::Api::Middleware, Rswag::Api.config
end
end
end
end

View File

@@ -0,0 +1,37 @@
require 'json'
module Rswag
module Api
class Middleware
def initialize(app, config)
@app = app
@config = config
end
def call(env)
path = env['PATH_INFO']
filename = "#{@config.resolve_swagger_root(env)}/#{path}"
if env['REQUEST_METHOD'] == 'GET' && File.file?(filename)
swagger = load_json(filename)
@config.swagger_filter.call(swagger, env) unless @config.swagger_filter.nil?
return [
'200',
{ 'Content-Type' => 'application/json' },
[ JSON.dump(swagger) ]
]
end
return @app.call(env)
end
private
def load_json(filename)
JSON.parse(File.read(filename))
end
end
end
end

View File

@@ -0,0 +1,5 @@
module Rswag
module Api
VERSION = '1.0.0'
end
end

View File

@@ -0,0 +1,18 @@
$:.push File.expand_path("../lib", __FILE__)
# Maintain your gem's version:
require 'rswag/api/version'
# Describe your gem and declare its dependencies:
Gem::Specification.new do |s|
s.name = "rswag-api"
s.version = Rswag::Api::VERSION
s.authors = ["Richie Morris"]
s.email = ["domaindrivendev@gmail.com"]
s.homepage = "https://github.com/domaindrivendev/rswag"
s.summary = "A Rails Engine that exposes Swagger files as JSON endpoints"
s.files = Dir["{app,config,db,lib}/**/*"] + ["MIT-LICENSE", "Rakefile" ]
s.add_dependency "rails", ">= 3.1", "< 5.1"
end

View File

@@ -0,0 +1,2 @@
TestApp::Application.routes.draw do
end

View File

@@ -0,0 +1,27 @@
require 'generator_spec'
require 'generators/rswag/api/install/install_generator'
module Rswag
module Api
describe InstallGenerator do
include GeneratorSpec::TestCase
destination File.expand_path('../tmp', __FILE__)
before(:all) do
prepare_destination
fixtures_dir = File.expand_path('../fixtures', __FILE__)
FileUtils.cp_r("#{fixtures_dir}/config", destination_root)
run_generator
end
it 'installs the Rails initializer' do
assert_file('config/initializers/rswag-api.rb')
end
# Don't know how to test this
#it 'wires up routes'
end
end
end

View File

@@ -0,0 +1,14 @@
Rswag::Api.configure do |c|
# Specify a root folder where Swagger JSON files are located
# This is used by the Swagger middleware to serve requests for API descriptions
# NOTE: If you're using rswag-specs to generate Swagger, you'll need to ensure
# that it's configured to generate files in the same folder
c.swagger_root = Rails.root.to_s + '/swagger'
# Inject a lamda function to alter the returned Swagger prior to serialization
# The function will have access to the rack env for the current request
# For example, you could leverage this to dynamically assign the "host" property
#
#c.swagger_filter = lambda { |swagger, env| swagger['host'] = env['HTTP_HOST'] }
end

View File

@@ -0,0 +1,4 @@
TestApp::Application.routes.draw do
mount Rswag::Api::Engine => '/api-docs'
end

View File

@@ -0,0 +1,6 @@
TestApp::Application.routes.draw do
resources :blogs, defaults: { :format => :json }
mount Rswag::Api::Engine => 'api-docs'
mount Rswag::Ui::Engine => 'api-docs'
end

View File

@@ -0,0 +1,8 @@
{
"swagger": "2.0",
"info": {
"title": "API V1",
"version": "v1"
},
"paths": {}
}

View File

@@ -0,0 +1,82 @@
require 'rswag/api/middleware'
require 'rswag/api/configuration'
module Rswag
module Api
describe Middleware do
let(:app) { double('app') }
let(:swagger_root) { File.expand_path('../fixtures/swagger', __FILE__) }
let(:config) do
Configuration.new.tap { |c| c.swagger_root = swagger_root }
end
subject { described_class.new(app, config) }
describe '#call(env)' do
let(:response) { subject.call(env) }
let(:env_defaults) do
{
'HTTP_HOST' => 'tempuri.org',
'REQUEST_METHOD' => 'GET',
}
end
context 'given a path that maps to an existing swagger file' do
let(:env) { env_defaults.merge('PATH_INFO' => 'v1/swagger.json') }
it 'returns a 200 status' do
expect(response.length).to eql(3)
expect(response.first).to eql('200')
end
it 'returns contents of the swagger file' do
expect(response.length).to eql(3)
expect(response[1]).to include( 'Content-Type' => 'application/json')
expect(response[2].join).to include('"title":"API V1"')
end
end
context "given a path that doesn't map to any swagger file" do
let(:env) { env_defaults.merge('PATH_INFO' => 'foobar.json') }
before do
allow(app).to receive(:call).and_return([ '500', {}, [] ])
end
it 'delegates to the next middleware' do
expect(response).to include('500')
end
end
context 'when the env contains a specific swagger_root' do
let(:env) do
env_defaults.merge(
'PATH_INFO' => 'v1/swagger.json',
'action_dispatch.request.path_parameters' => {
swagger_root: swagger_root
}
)
end
it 'locates files at the provided swagger_root' do
expect(response.length).to eql(3)
expect(response[1]).to include( 'Content-Type' => 'application/json')
expect(response[2].join).to include('"swagger":"2.0"')
end
end
context 'when a swagger_filter is configured' do
before do
config.swagger_filter = lambda { |swagger, env| swagger['host'] = env['HTTP_HOST'] }
end
let(:env) { env_defaults.merge('PATH_INFO' => 'v1/swagger.json') }
it 'applies the filter prior to serialization' do
expect(response.length).to eql(3)
expect(response[2].join).to include('"host":"tempuri.org"')
end
end
end
end
end
end

View File