Skip to content

Commit

Permalink
Allow OpenAPI 3.0 array query parameter schema (rswag#317)
Browse files Browse the repository at this point in the history
In OpenAPI 3.0, a query parameter can be specified like:

```
name: id
in: query
schema:
  type: array
  items:
    type: string
```
see: https://swagger.io/specification/#parameter-object

In order to support generating the correct OpenAPI 3.0 specification and
to still allow rswag specs to pass, this checks to see if `array` is
specified in the `type` of the parameter, or if it's specified in the
`schema: { type:` instead.

re: rswag#317
  • Loading branch information
diachini authored and Imran Iqbal committed Aug 27, 2020
1 parent 44a6150 commit 1b81862
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 3 deletions.
15 changes: 12 additions & 3 deletions rswag-specs/lib/rswag/specs/request_factory.rb
Original file line number Diff line number Diff line change
Expand Up @@ -111,14 +111,23 @@ def add_path(request, metadata, swagger_doc, parameters, example)

parameters.select { |p| p[:in] == :query }.each_with_index do |p, i|
path_template.concat(i.zero? ? '?' : '&')
path_template.concat(build_query_string_part(p, example.send(p[:name])))
path_template.concat(build_query_string_part(p, example.send(p[:name]), swagger_doc))
end
end
end

def build_query_string_part(param, value)
def param_is_array?(param)
param[:type]&.to_sym == :array || param.dig(:schema, :type)&.to_sym == :array
end

def build_query_string_part(param, value, swagger_doc)
name = param[:name]
return "#{name}=#{value}" unless param[:type].to_sym == :array

if doc_version(swagger_doc).start_with?('2')
return "#{name}=#{value}" unless param[:type].to_sym == :array
else # Openapi3
return "#{name}=#{value}" unless param_is_array?(param)
end

case param[:collectionFormat]
when :ssv
Expand Down
46 changes: 46 additions & 0 deletions rswag-specs/spec/rswag/specs/request_factory_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,52 @@ module Specs
end
end

context "'query' parameters of type 'array' by way of 'schema'" do
let(:swagger_doc) { { swagger: '3.0.3' } }

before do
metadata[:operation][:parameters] = [
{ name: 'things', in: :query, schema: { type: :array }, collectionFormat: collection_format }
]
allow(example).to receive(:things).and_return(['foo', 'bar'])
end

context 'collectionFormat = csv' do
let(:collection_format) { :csv }
it 'formats as comma separated values' do
expect(request[:path]).to eq('/blogs?things=foo,bar')
end
end

context 'collectionFormat = ssv' do
let(:collection_format) { :ssv }
it 'formats as space separated values' do
expect(request[:path]).to eq('/blogs?things=foo bar')
end
end

context 'collectionFormat = tsv' do
let(:collection_format) { :tsv }
it 'formats as tab separated values' do
expect(request[:path]).to eq('/blogs?things=foo\tbar')
end
end

context 'collectionFormat = pipes' do
let(:collection_format) { :pipes }
it 'formats as pipe separated values' do
expect(request[:path]).to eq('/blogs?things=foo|bar')
end
end

context 'collectionFormat = multi' do
let(:collection_format) { :multi }
it 'formats as multiple parameter instances' do
expect(request[:path]).to eq('/blogs?things=foo&things=bar')
end
end
end

context "'header' parameters" do
before do
metadata[:operation][:parameters] = [{ name: 'Api-Key', in: :header, type: :string }]
Expand Down

0 comments on commit 1b81862

Please sign in to comment.