Zorgoth
Zorgoth

Reputation: 671

How to combine apispec and flask-swagger-ui to make a Swagger page?

I can't find anything on the internet about how to actually extract and utilize the OpenAPI specification generated by the apispec package to make a Swagger page.

I don't want to rely on a package that hasn't been being actively maintained like flask-apispec. I want to use flask-swagger-ui, apispec, and other standard/well-maintained packages only.

Here is my test app. I don't know if the APISpec is working right because the documentation doesn't tell you anything about what you do with the object, but the Flask app is functional.

from flask import Flask, request, abort
from marshmallow import Schema, fields
from apispec import APISpec
from apispec.ext.marshmallow import MarshmallowPlugin
from apispec_webframeworks.flask import FlaskPlugin


app = Flask(__name__)


spec = APISpec(
    title="Doubler",
    version="1.0.0",
    openapi_version="3.0.2",
    plugins=[FlaskPlugin(), MarshmallowPlugin()],
              )


class InputSchema(Schema):
    useless_1 = fields.String(required=True, description='A string')
    useless_2 = fields.Int(missing=5, description='An integer')


class OutputSchema(Schema):
    doublyuseless_1 = fields.String(required=True)
    doublyuseless_2 = fields.Int(required=True)


inputschema = InputSchema()
outputschema = OutputSchema()


@app.route('/double', methods=['GET'])
def double():
    """A doubler.
    ---
    get:
      description: Double things
      parameters:
        schema:
          InputSchema
      responses:
        200:
          description: Double things
          content:
            application/json:
              schema: OutputSchema"""
    errors = inputschema.validate(request.args)
    if errors:
        abort(400, str(errors))
    return_dict = {}
    args = inputschema.load(request.args)
    return_dict['doublyuseless_1'] = args['useless_1']*2
    return_dict['doublyuseless_2'] = args['useless_2']*2
    return outputschema.dump(return_dict)


with app.test_request_context():
    spec.path(view=double)

UPDATE: with the following code, I now get a blank page at root with the Swagger title, but no content.

with app.test_request_context():
    spec.path(view=double)
    with open('swagger.json', 'w') as f:
        dict_ = yaml.load(StringIO(spec.to_yaml()), Loader=yaml.SafeLoader)
        print(dict_)
        with open('swagger.json', 'w') as f:
            json.dump(dict_, f)
    SWAGGER_URL = '/'
    API_URL = 'swagger.json'


swaggerui_blueprint = get_swaggerui_blueprint(
    SWAGGER_URL,  # Swagger UI static files will be mapped to '{SWAGGER_URL}/dist/'
    API_URL,
    config={  # Swagger UI config overrides
        'app_name': "Doubler"
    },
    # oauth_config={  # OAuth config. See https://github.com/swagger-api/swagger-ui#oauth2-configuration .
    #    'clientId': "your-client-id",
    #    'clientSecret': "your-client-secret-if-required",
    #    'realm': "your-realms",
    #    'appName': "your-app-name",
    #    'scopeSeparator': " ",
    #    'additionalQueryStringParams': {'test': "hello"}
    # }
)

Upvotes: 1

Views: 1946

Answers (1)

Zorgoth
Zorgoth

Reputation: 671

The solution to my original problem was quite straightforward: ApiSpec has both a to_dict and a to_yaml method for exporting swagger.json. My second problem was more esoteric. I needed to use a SWAGGER_URL that was not /, because for some reason this caused the page to look for the core Swagger files at URLs like http://swagger-ui.js, which obviously didn't work. Once I changed my path to /doc, I still had a white screen, but that could be fixed by hosting the files myself at /doc (which I think flask_swagger_ui was supposed to do automatically, but hey, it worked).

Upvotes: 1

Related Questions