Rswag: How to set response schema (model)?

Created on 21 Dec 2019  路  4Comments  路  Source: rswag/rswag

How to set response schema? I mean the model section for openapi ver. 3.0.1...

model

My a code:

require 'swagger_helper'

RSpec.describe "Hello World API" do
  path "/hello" do
    get "Shows a Hello World" do
      tags "Hello"
      produces "application/json"

      response "200", "hello world found" do
        schema type: :object, properties: {
          hello: {type: :string}
        }, required: ["hello"]

        examples "application/json" => {
          hello: "world"
        }

        run_test!
      end
    end
  end
end

Most helpful comment

Hi @martio, I've just come against the same problem with 2.2.0.

The schema definition in your spec is used to validate the content of the response, but it looks like it's generating an OpenAPI output in the wrong place. The generated swagger.yaml looks like this:

paths:
  "/hello":
    get:
      summary: Shows a Hello World
      tags:
      - Hello
      produces:
      - application/json
      responses:
        '200':
          description: hello world found
          schema:
            type: object
            properties:
              hello:
                type: string
            required:
            - hello
          examples:
            application/json:
              hello: world

In the example above schema is a child of '200'.

However, the OpenAPI 3.0.1 ResponseObject spec describes the schema element as belonging within a content and application/json (or whatever your content type is) block.

If we move the schema to match the schema it works in swagger-ui:

paths:
  "/hello":
    get:
      summary: Shows a Hello World
      tags:
      - Hello
      produces:
      - application/json
      responses:
        '200':
          description: hello world found
          content:
            application/json:
              schema:
                type: object
                properties:
                  hello:
                    type: string
                required:
                - hello
          examples:
            application/json:
              hello: world

produces:
Screenshot 2020-01-03 10 21 43

Obviously we don't want to be updating the yaml by hand, so we can work around this by adding the metadata in the spec:

RSpec.describe "Hello World API" do
  path "/hello" do
    get "Shows a Hello World" do
      tags "Hello"
      produces "application/json"

      response "200", "hello world found" do

        # Adds model metadata for Swagger UI. Should match the schema definition below
        metadata[:response][:content] = { "application/json": {
            schema: {
              type: :object, properties: {
                        hello: {type: :string}
                      }, required: ["hello"]
            }
          }
        }
        schema type: :object, properties: {
          hello: {type: :string}
        }, required: ["hello"]

        examples "application/json" => {
          hello: "world"
        }

        run_test!
      end
    end
  end
end

if you add this _as well as_ the schema definition you already have, the content will be validated against the schema _and_ it'll work in the swagger UI.

In summary:

Expected behaviour

  • Adding a schema definition in the test generates a schema block as follows:
responses:
   '200':
    content:
      application/json:
        schema: ...

Actual behaviour

  • The schema block is generated within the response code block (e.g. '200').
responses:
  '200':
    schema: ...

All 4 comments

Hi @martio, I've just come against the same problem with 2.2.0.

The schema definition in your spec is used to validate the content of the response, but it looks like it's generating an OpenAPI output in the wrong place. The generated swagger.yaml looks like this:

paths:
  "/hello":
    get:
      summary: Shows a Hello World
      tags:
      - Hello
      produces:
      - application/json
      responses:
        '200':
          description: hello world found
          schema:
            type: object
            properties:
              hello:
                type: string
            required:
            - hello
          examples:
            application/json:
              hello: world

In the example above schema is a child of '200'.

However, the OpenAPI 3.0.1 ResponseObject spec describes the schema element as belonging within a content and application/json (or whatever your content type is) block.

If we move the schema to match the schema it works in swagger-ui:

paths:
  "/hello":
    get:
      summary: Shows a Hello World
      tags:
      - Hello
      produces:
      - application/json
      responses:
        '200':
          description: hello world found
          content:
            application/json:
              schema:
                type: object
                properties:
                  hello:
                    type: string
                required:
                - hello
          examples:
            application/json:
              hello: world

produces:
Screenshot 2020-01-03 10 21 43

Obviously we don't want to be updating the yaml by hand, so we can work around this by adding the metadata in the spec:

RSpec.describe "Hello World API" do
  path "/hello" do
    get "Shows a Hello World" do
      tags "Hello"
      produces "application/json"

      response "200", "hello world found" do

        # Adds model metadata for Swagger UI. Should match the schema definition below
        metadata[:response][:content] = { "application/json": {
            schema: {
              type: :object, properties: {
                        hello: {type: :string}
                      }, required: ["hello"]
            }
          }
        }
        schema type: :object, properties: {
          hello: {type: :string}
        }, required: ["hello"]

        examples "application/json" => {
          hello: "world"
        }

        run_test!
      end
    end
  end
end

if you add this _as well as_ the schema definition you already have, the content will be validated against the schema _and_ it'll work in the swagger UI.

In summary:

Expected behaviour

  • Adding a schema definition in the test generates a schema block as follows:
responses:
   '200':
    content:
      application/json:
        schema: ...

Actual behaviour

  • The schema block is generated within the response code block (e.g. '200').
responses:
  '200':
    schema: ...

I've added the following into my swagger_helper.json to automatically apply the workaround above to any swagger specs:

RSpec.configure do |config|
  config.after do |example|
    # if there's no response metadata, we can assume we're not in RSwag territory
    unless example.metadata[:response].nil?
      example.metadata[:response][:content] = {
        example.metadata[:operation][:produces].first => {
          schema: example.metadata[:response][:schema]
        }
      }
    end
  end
end

Having the same issue

@martio what worked for me was adding to the schema to the response block like so:

response '200', 'blog found' do
        schema type: :object,
          properties: {
            id: { type: :integer },
            title: { type: :string },
            content: { type: :string }
          },
          required: [ 'id', 'title', 'content' ]

        let(:id) { Blog.create(title: 'foo', content: 'bar').id }
        run_test!
      end

I have had a similar issue. We initially generated documentation in Swagger v2 because when we tried generating it in OpenAPI v3 the response schemas were missing even though they were defined in our specs. After walking through the code I discovered our problem was that we had provided consumes but not produces on our responses.

The schema provided in https://github.com/rswag/rswag/issues/268#issue-541343154 has the inverse -- it has produces but not consumes. But I suspect that causes the same problem where the response schema is not output.

In OpenAPI v3 a single path and status code can have multiple responses that differ by response mime-type. So instead of Swagger v2's produces and consumes keys, OpenAPI v3's response schema looks something like:

responses:
  '200':
    description: something
    content:
      application/json:
        schema:
          type: object
          properties: ...

Nevertheless, I think we could get better diagnostic messages from rswag. It seems like multiple folks have hit this and it would have been nice to have some more information on why I wasn't getting the response schemas.

Starting at https://github.com/rswag/rswag/blob/0aca50c66c32d169754a476721d66522ebaee968/rswag-specs/lib/rswag/specs/swagger_formatter.rb#L23 the first conditions that cause us to not generate a response schema are at https://github.com/rswag/rswag/blob/0aca50c66c32d169754a476721d66522ebaee968/rswag-specs/lib/rswag/specs/swagger_formatter.rb#L33-L34

Which is to say our spec needs a response. Next condition is at https://github.com/rswag/rswag/blob/0aca50c66c32d169754a476721d66522ebaee968/rswag-specs/lib/rswag/specs/swagger_formatter.rb#L38

Which means we need to be using OpenAPI v3 and not Swagger v2.

Then we call into https://github.com/rswag/rswag/blob/0aca50c66c32d169754a476721d66522ebaee968/rswag-specs/lib/rswag/specs/swagger_formatter.rb#L45

Full definition at https://github.com/rswag/rswag/blob/0aca50c66c32d169754a476721d66522ebaee968/rswag-specs/lib/rswag/specs/swagger_formatter.rb#L124-L130

Line 126 means we either need to provide a document-level produces or an spec-level one.

The actual work is done in upgrade_content! https://github.com/rswag/rswag/blob/0aca50c66c32d169754a476721d66522ebaee968/rswag-specs/lib/rswag/specs/swagger_formatter.rb#L132-L141

Line 134 means we do not generate a response if we don't have a schema or if we never provided any produces.

Once I added produces to my specs I passed that early return and Line 139 and generated the right YAML for OpenAPI v3.

I hope that helps other folks debug why they might not be getting any response schema output from OpenAPI v3 even when it works just fine in Swagger v2.

Maybe we could add a log message or warning when someone is:

  • Using OpenAPI v3
  • Missing a produces or consumes
  • Provides a response with a schema
Was this page helpful?
0 / 5 - 0 ratings

Related issues

anjum-ahmed picture anjum-ahmed  路  6Comments

hannesstruss picture hannesstruss  路  6Comments

abevoelker picture abevoelker  路  4Comments

DalfDev picture DalfDev  路  3Comments

richthedev picture richthedev  路  5Comments