Как сгенерировать машиночитаемую спецификацию yaml существующего API, написанного на flask-restplus?

У меня есть простой API, написанный с помощью flask-restplus:

from flask import Flask
from flask_restplus import Resource, Api

app = Flask(__name__)                  #  Create a Flask WSGI application
api = Api(app)                         #  Create a Flask-RESTPlus API

@api.route('/hello')                   #  Create a URL route to this resource
class HelloWorld(Resource):            #  Create a RESTful resource
    def get(self):                     #  Create GET endpoint
        return {'hello': 'world'}

if __name__ == '__main__':
    app.run(debug=True) 

Когда я перехожу к loacalhost:5000/ в браузере я получаю базовую документацию по Swagger, но не могу найти, где я могу получить машиночитаемое представление простого yaml API, не должно ли оно также генерироваться автоматически?

1 ответ

Решение

Я не смог найти никакой информации о "генерации документации Swagger Yaml" в официальных документациях на flask-restplus. Итак, я решил изучить исходный код и обнаружил, что Swagger Класс реализует генерацию документации Swagger для экземпляра API.

Swagger класс в исходном коде flask-restplus является оболочкой документации Swagger для экземпляра API. Все методы в этом классе предполагают, что данные API сериализуются в виде словаря JSON. Например, рассмотрим as_dict() функция этого класса, которая сериализует полную спецификацию Swagger как сериализуемый dict. Посмотрите на строку документации для этой функции:

from flask import Flask
from flask_restplus import Resource, Api
from flask_restplus.api import Swagger

app = Flask(__name__)                  
api = Api(app)

swag = Swagger(api)
print(swag.as_dict.__doc__) 

#Output:
Output the specification as a serializable ``dict``.

    :returns: the full Swagger specification in a serializable format
    :rtype: dict

Возможно, я ошибаюсь, но исходный код предполагает, что документация по API возвращается только как JSON который доступен на http://localhost:5000/swagger.json по умолчанию. Я не мог найти что-нибудь для YAML.

Но есть обходной путь для создания документации YAML для вашего API. Я использовал json а также yaml библиотеки, чтобы сбросить ответ JSON от /swagger.json в YAML и сохранить его в yamldoc.yml, Вы можете вызвать это, перейдя в http://localhost:5000/swagger.yml, Полный код:

from flask import Flask
from flask_restplus import Resource, Api
from flask_restplus.api import Swagger
import requests
import json, yaml

app = Flask(__name__)                  #  Create a Flask WSGI application
api = Api(app)                         #  Create a Flask-RESTPlus API

@api.route('/hello')                   #  Create a URL route to this resource
class HelloWorld(Resource):            #  Create a RESTful resource
    def get(self):                  
        return {'hello': 'world'}

@api.route('/swagger.yml')
class HelloWorld(Resource):    
    def get(self):
       url = 'http://localhost:5000/swagger.json'       
       resp = requests.get(url)
       data = json.loads(resp.content)    
       with open('yamldoc.yml', 'w') as yamlf:
           yaml.dump(data, yamlf, allow_unicode=True)
       return {"message":"Yaml document generated!"}


if __name__ == '__main__':
    app.run(debug=True) 

Надеюсь, это поможет.

Из ответа @amanb я заставил свой api вернуть файл yaml без каких-либо запросов. Согласно документации flask restplus (или самой последней вилки flask restx), можно экспортировать спецификации Swagger, соответствующие вашему API, используя:

from flask import json

from myapp import api

print(json.dumps(api.__schema__))

Итак, вместо использования requests Я предпочел использовать api.__schema__.

Поскольку моя цель - предоставить файл для загрузки во время запроса, необходимо использовать send_file функция Flask. Кроме того, этот файл можно позже удалить из каталога, чтобы мы могли использоватьafter_this_request декоратор Flaskдля вызова аннотированной функции, которая удалит файл. Полный код:

import os
import json
import yaml

from flask import Flask, after_this_request, send_file, safe_join, abort
from flask_restplus import Resource, Api
from flask_restplus.api import Swagger


app = Flask(__name__)                  #  Create a Flask WSGI application
api = Api(app)                         #  Create a Flask-RESTPlus API

@api.route('/hello')                   #  Create a URL route to this resource
class HelloWorld(Resource):            #  Create a RESTful resource
    def get(self):                  
        return {'hello': 'world'}

@api.route('/swagger.yml')
class HelloWorld(Resource):    
    def get(self):
       data = json.loads(json.dumps(api.__schema__))
       with open('yamldoc.yml', 'w') as yamlf:
           yaml.dump(data, yamlf, allow_unicode=True, default_flow_style=False)
           file = os.path.abspath(os.getcwd())
           try:
               @after_this_request
               def remove_file(resp):
                   try:
                       os.remove(safe_join(file, 'yamldoc.yml'))
                   except Exception as error:
                       log.error("Error removing or closing downloaded file handle", error)
                   return resp

               return send_file(safe_join(file, 'yamldoc.yml'), as_attachment=True, attachment_filename='yamldoc.yml', mimetype='application/x-yaml')
           except FileExistsError:
               abort(404)


if __name__ == '__main__':
    app.run(debug=True) 

Другие вопросы по тегам