mirror of
https://github.com/ditkrg/rswag.git
synced 2026-01-22 22:06:43 +00:00
Initial commit for trying to produce and consume v3 swagger
This commit is contained in:
parent
10bb732148
commit
768a1a1d43
1
.gitignore
vendored
1
.gitignore
vendored
@ -6,3 +6,4 @@
|
|||||||
**/*/node_modules
|
**/*/node_modules
|
||||||
*.swp
|
*.swp
|
||||||
Gemfile.lock
|
Gemfile.lock
|
||||||
|
/.idea/
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
2.3.1
|
2.5.1
|
||||||
|
|||||||
2
Gemfile
2
Gemfile
@ -13,7 +13,7 @@ when '4', '5'
|
|||||||
gem 'responders'
|
gem 'responders'
|
||||||
end
|
end
|
||||||
|
|
||||||
gem 'sqlite3'
|
gem 'sqlite3', '~> 1.3.6'
|
||||||
|
|
||||||
gem 'rswag-api', path: './rswag-api'
|
gem 'rswag-api', path: './rswag-api'
|
||||||
gem 'rswag-ui', path: './rswag-ui'
|
gem 'rswag-ui', path: './rswag-ui'
|
||||||
|
|||||||
@ -35,6 +35,14 @@ module Rswag
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#TODO: look at adding request_body method to handle diffs in Open API 2.0 to 3.0
|
||||||
|
# https://swagger.io/docs/specification/describing-request-body/
|
||||||
|
# need to make sure we output requestBody in the swagger generator .json
|
||||||
|
# also need to make sure that it can handle content: , required: true/false, schema: ref
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def parameter(attributes)
|
def parameter(attributes)
|
||||||
if attributes[:in] && attributes[:in].to_sym == :path
|
if attributes[:in] && attributes[:in].to_sym == :path
|
||||||
attributes[:required] = true
|
attributes[:required] = true
|
||||||
|
|||||||
@ -15,7 +15,7 @@ module Rswag
|
|||||||
class ExtendedTypeAttribute < JSON::Schema::TypeV4Attribute
|
class ExtendedTypeAttribute < JSON::Schema::TypeV4Attribute
|
||||||
|
|
||||||
def self.validate(current_schema, data, fragments, processor, validator, options={})
|
def self.validate(current_schema, data, fragments, processor, validator, options={})
|
||||||
return if data.nil? && current_schema.schema['x-nullable'] == true
|
return if data.nil? && (current_schema.schema['nullable'] == true || current_schema.schema['x-nullable'] == true)
|
||||||
super
|
super
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -39,7 +39,7 @@ module Rswag
|
|||||||
def derive_security_params(metadata, swagger_doc)
|
def derive_security_params(metadata, swagger_doc)
|
||||||
requirements = metadata[:operation][:security] || swagger_doc[:security] || []
|
requirements = metadata[:operation][:security] || swagger_doc[:security] || []
|
||||||
scheme_names = requirements.flat_map { |r| r.keys }
|
scheme_names = requirements.flat_map { |r| r.keys }
|
||||||
schemes = (swagger_doc[:securityDefinitions] || {}).slice(*scheme_names).values
|
schemes = (swagger_doc[:components][:securitySchemes] || {}).slice(*scheme_names).values
|
||||||
|
|
||||||
schemes.map do |scheme|
|
schemes.map do |scheme|
|
||||||
param = (scheme[:type] == :apiKey) ? scheme.slice(:name, :in) : { name: 'Authorization', in: :header }
|
param = (scheme[:type] == :apiKey) ? scheme.slice(:name, :in) : { name: 'Authorization', in: :header }
|
||||||
|
|||||||
@ -41,9 +41,12 @@ module Rswag
|
|||||||
response_schema = metadata[:response][:schema]
|
response_schema = metadata[:response][:schema]
|
||||||
return if response_schema.nil?
|
return if response_schema.nil?
|
||||||
|
|
||||||
|
components_schemas = {components: {schemas: swagger_doc[:components][:schemas]}}
|
||||||
|
|
||||||
validation_schema = response_schema
|
validation_schema = response_schema
|
||||||
.merge('$schema' => 'http://tempuri.org/rswag/specs/extended_schema')
|
.merge('$schema' => 'http://tempuri.org/rswag/specs/extended_schema')
|
||||||
.merge(swagger_doc.slice(:definitions))
|
.merge(components_schemas)
|
||||||
|
|
||||||
errors = JSON::Validator.fully_validate(validation_schema, body)
|
errors = JSON::Validator.fully_validate(validation_schema, body)
|
||||||
raise UnexpectedResponse, "Expected response body to match schema: #{errors[0]}" if errors.any?
|
raise UnexpectedResponse, "Expected response body to match schema: #{errors[0]}" if errors.any?
|
||||||
end
|
end
|
||||||
|
|||||||
@ -10,7 +10,7 @@ describe 'Blogs API', type: :request, swagger_doc: 'v1/swagger.json' do
|
|||||||
operationId 'createBlog'
|
operationId 'createBlog'
|
||||||
consumes 'application/json'
|
consumes 'application/json'
|
||||||
produces 'application/json'
|
produces 'application/json'
|
||||||
parameter name: :blog, in: :body, schema: { '$ref' => '#/definitions/blog' }
|
parameter name: :blog, in: :body, schema: { '$ref' => '#/components/schemas/blog' }
|
||||||
|
|
||||||
let(:blog) { { title: 'foo', content: 'bar' } }
|
let(:blog) { { title: 'foo', content: 'bar' } }
|
||||||
|
|
||||||
@ -19,7 +19,7 @@ describe 'Blogs API', type: :request, swagger_doc: 'v1/swagger.json' do
|
|||||||
end
|
end
|
||||||
|
|
||||||
response '422', 'invalid request' do
|
response '422', 'invalid request' do
|
||||||
schema '$ref' => '#/definitions/errors_object'
|
schema '$ref' => '#/components/schemas/errors_object'
|
||||||
|
|
||||||
let(:blog) { { title: 'foo' } }
|
let(:blog) { { title: 'foo' } }
|
||||||
run_test! do |response|
|
run_test! do |response|
|
||||||
@ -38,7 +38,7 @@ describe 'Blogs API', type: :request, swagger_doc: 'v1/swagger.json' do
|
|||||||
let(:keywords) { 'foo bar' }
|
let(:keywords) { 'foo bar' }
|
||||||
|
|
||||||
response '200', 'success' do
|
response '200', 'success' do
|
||||||
schema type: 'array', items: { '$ref' => '#/definitions/blog' }
|
schema type: 'array', items: { '$ref' => '#/components/schemas/blog' }
|
||||||
end
|
end
|
||||||
|
|
||||||
response '406', 'unsupported accept header' do
|
response '406', 'unsupported accept header' do
|
||||||
@ -65,7 +65,7 @@ describe 'Blogs API', type: :request, swagger_doc: 'v1/swagger.json' do
|
|||||||
header 'Last-Modified', type: :string
|
header 'Last-Modified', type: :string
|
||||||
header 'Cache-Control', type: :string
|
header 'Cache-Control', type: :string
|
||||||
|
|
||||||
schema '$ref' => '#/definitions/blog'
|
schema '$ref' => '#/components/schemas/blog'
|
||||||
|
|
||||||
examples 'application/json' => {
|
examples 'application/json' => {
|
||||||
id: 1,
|
id: 1,
|
||||||
|
|||||||
@ -14,47 +14,61 @@ RSpec.configure do |config|
|
|||||||
# the root example_group in your specs, e.g. describe '...', swagger_doc: 'v2/swagger.json'
|
# the root example_group in your specs, e.g. describe '...', swagger_doc: 'v2/swagger.json'
|
||||||
config.swagger_docs = {
|
config.swagger_docs = {
|
||||||
'v1/swagger.json' => {
|
'v1/swagger.json' => {
|
||||||
swagger: '2.0',
|
openapi: '3.0.0',
|
||||||
info: {
|
info: {
|
||||||
title: 'API V1',
|
title: 'API V1',
|
||||||
version: 'v1'
|
version: 'v1'
|
||||||
},
|
},
|
||||||
paths: {},
|
paths: {},
|
||||||
definitions: {
|
servers: [
|
||||||
errors_object: {
|
{
|
||||||
type: 'object',
|
url: "https://{defaultHost}",
|
||||||
properties: {
|
variables: {
|
||||||
errors: { '$ref' => '#/definitions/errors_map' }
|
defaultHost: {
|
||||||
|
default: "www.example.com"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
components: {
|
||||||
|
schemas: {
|
||||||
|
errors_object: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
errors: { '$ref' => '#/components/schemas/errors_map' }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
errors_map: {
|
||||||
|
type: 'object',
|
||||||
|
additionalProperties: {
|
||||||
|
type: 'array',
|
||||||
|
items: { type: 'string' }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
blog: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
id: { type: 'integer' },
|
||||||
|
title: { type: 'string' },
|
||||||
|
content: { type: 'string', nullable: true },
|
||||||
|
thumbnail: { type: 'string'}
|
||||||
|
},
|
||||||
|
required: [ 'id', 'title', 'content', 'thumbnail' ]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
errors_map: {
|
securitySchemes: {
|
||||||
type: 'object',
|
basic_auth: {
|
||||||
additionalProperties: {
|
type: :http,
|
||||||
type: 'array',
|
scheme: :basic
|
||||||
items: { type: 'string' }
|
},
|
||||||
}
|
api_key: {
|
||||||
},
|
type: :apiKey,
|
||||||
blog: {
|
name: 'api_key',
|
||||||
type: 'object',
|
in: :query
|
||||||
properties: {
|
}
|
||||||
id: { type: 'integer' },
|
|
||||||
title: { type: 'string' },
|
|
||||||
content: { type: 'string', 'x-nullable': true },
|
|
||||||
thumbnail: { type: 'string'}
|
|
||||||
},
|
|
||||||
required: [ 'id', 'title', 'content', 'thumbnail' ]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
securityDefinitions: {
|
|
||||||
basic_auth: {
|
|
||||||
type: :basic
|
|
||||||
},
|
|
||||||
api_key: {
|
|
||||||
type: :apiKey,
|
|
||||||
name: 'api_key',
|
|
||||||
in: :query
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"swagger": "2.0",
|
"openapi": "3.0.0",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "API V1",
|
"title": "API V1",
|
||||||
"version": "v1"
|
"version": "v1"
|
||||||
@ -99,7 +99,7 @@
|
|||||||
"name": "blog",
|
"name": "blog",
|
||||||
"in": "body",
|
"in": "body",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/definitions/blog"
|
"$ref": "#/components/schemas/blog"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -110,7 +110,7 @@
|
|||||||
"422": {
|
"422": {
|
||||||
"description": "invalid request",
|
"description": "invalid request",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/definitions/errors_object"
|
"$ref": "#/components/schemas/errors_object"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -173,7 +173,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/definitions/blog"
|
"$ref": "#/components/schemas/blog"
|
||||||
},
|
},
|
||||||
"examples": {
|
"examples": {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
@ -225,57 +225,70 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"definitions": {
|
"servers": [
|
||||||
"errors_object": {
|
{
|
||||||
"type": "object",
|
"url": "https://{defaultHost}",
|
||||||
"properties": {
|
"variables": {
|
||||||
"errors": {
|
"defaultHost": {
|
||||||
"$ref": "#/definitions/errors_map"
|
"default": "www.example.com"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"errors_map": {
|
],
|
||||||
"type": "object",
|
"components": {
|
||||||
"additionalProperties": {
|
"schemas": {
|
||||||
"type": "array",
|
"errors_object": {
|
||||||
"items": {
|
"type": "object",
|
||||||
"type": "string"
|
"properties": {
|
||||||
}
|
"errors": {
|
||||||
}
|
"$ref": "#/components/schemas/errors_map"
|
||||||
},
|
}
|
||||||
"blog": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"id": {
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"title": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"content": {
|
|
||||||
"type": "string",
|
|
||||||
"x-nullable": true
|
|
||||||
},
|
|
||||||
"thumbnail": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"errors_map": {
|
||||||
"id",
|
"type": "object",
|
||||||
"title",
|
"additionalProperties": {
|
||||||
"content",
|
"type": "array",
|
||||||
"thumbnail"
|
"items": {
|
||||||
]
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"securityDefinitions": {
|
},
|
||||||
"basic_auth": {
|
"blog": {
|
||||||
"type": "basic"
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"title": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"content": {
|
||||||
|
"type": "string",
|
||||||
|
"nullable": true
|
||||||
|
},
|
||||||
|
"thumbnail": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id",
|
||||||
|
"title",
|
||||||
|
"content",
|
||||||
|
"thumbnail"
|
||||||
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"api_key": {
|
"securitySchemes": {
|
||||||
"type": "apiKey",
|
"basic_auth": {
|
||||||
"name": "api_key",
|
"type": "http",
|
||||||
"in": "query"
|
"scheme": "basic"
|
||||||
|
},
|
||||||
|
"api_key": {
|
||||||
|
"type": "apiKey",
|
||||||
|
"name": "api_key",
|
||||||
|
"in": "query"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user