External YAML with multiple specs not working on Flasgger

1.4k views Asked by At

I'm trying to document multiple endpoints by reference to the same YAML file but it just won't work. Is this not supported? Or am I doing something wrong?

app.py

from flask import Flask, jsonify
from flasgger import Swagger

app = Flask(__name__)
Swagger(app)

@app.route('/colors1/<palette>/')
def colors1(palette):
    """
    file: ../colors.yaml
    """
    all_colors = {
        'cmyk': ['cyan', 'magenta', 'yellow', 'black'],
        'rgb': ['red', 'green', 'blue']
    }
    if palette == 'all':
        result = all_colors
    else:
        result = {palette: all_colors.get(palette)}

    return jsonify(result)

@app.route('/colors2/<palette>/')
def colors2(palette):
    """
    file: ../colors.yaml
    """
    all_colors = {
        'cmyk': ['cyan', 'magenta', 'yellow', 'black'],
        'rgb': ['red', 'green', 'blue']
    }
    if palette == 'all':
        result = all_colors
    else:
        result = {palette: all_colors.get(palette)}

    return jsonify(result)

colors.yaml

Multiple endpoint specs
---
paths:
  /colors1/:
    get:
      parameters:
        - name: palette
          in: path
          type: string
          enum: ['all', 'rgb', 'cmyk']
          required: true
          default: all
      responses:
        200:
          description: A list of colors (may be filtered by palette)
          schema:
            $ref: '#/components/schema/Palette'
          examples:
            rgb: ['red', 'green', 'blue']
  /colors2/:
    get:
      parameters:
        - name: palette
          in: path
          type: string
          enum: ['all', 'rgb', 'cmyk']
          required: true
          default: all
      responses:
        200:
          description: A list of colors (may be filtered by palette)
          schema:
            $ref: '#/components/schema/Palette'
          examples:
            rgb: ['red', 'green', 'blue']
components:
  schemas:
    Palette:
      type: object
      properties:
        palette_name:
          type: array
          items:
            $ref: '#/components/schema/Color'
    Color:
      type: string

Expected result

Two endpoints with full specs (examples, response, parameters, etc), just like the specs in the screenshot in the README.

Actual result

Incomplete specs with a lot of details missing:

image

1

There are 1 answers

2
Sasha On

Why it doesn't work?

Flasgger doesn't seem to support having multiple specs in a single external YAML file. So you will need to put each endpoint spec in a separate file.

Why are details missing in Swagger-UI?

There are few problems in your colors.yaml file:

Solution 1. Use OpenAPI 2.0

Here is how colors.yaml should look so Flasgger can understand it

Colors endpoint spec
---

parameters:
  - name: palette
    in: path
    type: string
    enum:
      - all
      - rgb
      - cmyk
    required: true
    default: all

responses:
  '200':
    description: A list of colors (may be filtered by palette)
    schema:
      $ref: '#/definitions/Palette'
    examples:
      rgb:
        - red
        - green
        - blue

definitions:
  Palette:
    type: object
    properties:
      palette_name:
        type: array
        items:
          $ref: '#/definitions/Color'
    example:
      rgb:
        - red
        - green
        - blue
  Color:
    type: string
    example: red

Solution 2. Use OpenAPI 3 (not fully supported by Flasgger)

According to Flasgger repo, OpenAPI 3 support is experimental

There is experimental support for OpenAPI 3.0 that should work when using SwaggerUI 3.

So using Flasgger in OpenAPI 3 mode with external spec files is possible, but not all cases are supported. For example, there is an open issue about using components reference with external YAML file (see issue #308).

If you are still up to it, here is what you should do.

Step 1. Enable OpenAPI 3

Update app.config in your app.py file:

app = Flask(__name__)
app.config['SWAGGER'] = {
    'openapi': '3.0.0'
}
swagger = Swagger(app)

Step 2. Update specs to use OpenAPI 3

Update your colors.yaml file with the following content.

Important: Please note that we had to inline model schema definitions instead of using $ref spec due to the issue mentioned above.

Colors endpoint spec
---

parameters:
  - name: palette
    in: path
    schema:
      type: string
      enum: ['all', 'rgb', 'cmyk']
      default: all
    required: true

responses:
  200:
    description: A list of colors (may be filtered by palette)
    content:
      application/json:
        schema:
          type: object
          properties:
            palette_name:
              type: array
              items:
                type: string
                example: red
          example:
            rgb:
              - red
              - green
              - blue
        example:
          rgb: ['red', 'green', 'blue']