mirror of
https://github.com/ditkrg/rswag.git
synced 2026-01-25 07:16:40 +00:00
rename to rswag plus major refactor - almost a rewrite
This commit is contained in:
2
rswag-api/.rspec
Normal file
2
rswag-api/.rspec
Normal file
@@ -0,0 +1,2 @@
|
||||
--color
|
||||
--require spec_helper
|
||||
20
rswag-api/MIT-LICENSE
Normal file
20
rswag-api/MIT-LICENSE
Normal 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
27
rswag-api/Rakefile
Normal 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
12
rswag-api/bin/rails
Executable 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'
|
||||
8
rswag-api/lib/generators/rswag/api/install/USAGE
Normal file
8
rswag-api/lib/generators/rswag/api/install/USAGE
Normal 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
|
||||
@@ -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
|
||||
@@ -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
|
||||
15
rswag-api/lib/rswag/api.rb
Normal file
15
rswag-api/lib/rswag/api.rb
Normal 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
|
||||
12
rswag-api/lib/rswag/api/configuration.rb
Normal file
12
rswag-api/lib/rswag/api/configuration.rb
Normal 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
|
||||
13
rswag-api/lib/rswag/api/engine.rb
Normal file
13
rswag-api/lib/rswag/api/engine.rb
Normal 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
|
||||
37
rswag-api/lib/rswag/api/middleware.rb
Normal file
37
rswag-api/lib/rswag/api/middleware.rb
Normal 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
|
||||
5
rswag-api/lib/rswag/api/version.rb
Normal file
5
rswag-api/lib/rswag/api/version.rb
Normal file
@@ -0,0 +1,5 @@
|
||||
module Rswag
|
||||
module Api
|
||||
VERSION = '1.0.0'
|
||||
end
|
||||
end
|
||||
18
rswag-api/rswag-api.gemspec
Normal file
18
rswag-api/rswag-api.gemspec
Normal 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
|
||||
@@ -0,0 +1,2 @@
|
||||
TestApp::Application.routes.draw do
|
||||
end
|
||||
@@ -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
|
||||
@@ -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
|
||||
4
rswag-api/spec/generators/rswag/api/tmp/config/routes.rb
Normal file
4
rswag-api/spec/generators/rswag/api/tmp/config/routes.rb
Normal file
@@ -0,0 +1,4 @@
|
||||
TestApp::Application.routes.draw do
|
||||
mount Rswag::Api::Engine => '/api-docs'
|
||||
|
||||
end
|
||||
6
rswag-api/spec/rswag/api/fixtures/config/routes.rb
Normal file
6
rswag-api/spec/rswag/api/fixtures/config/routes.rb
Normal 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
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"swagger": "2.0",
|
||||
"info": {
|
||||
"title": "API V1",
|
||||
"version": "v1"
|
||||
},
|
||||
"paths": {}
|
||||
}
|
||||
82
rswag-api/spec/rswag/api/middleware_spec.rb
Normal file
82
rswag-api/spec/rswag/api/middleware_spec.rb
Normal 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
|
||||
0
rswag-api/spec/spec_helper.rb
Normal file
0
rswag-api/spec/spec_helper.rb
Normal file
Reference in New Issue
Block a user