Обслуживание Flask-RESTPlus на https-сервере

Я относительно новичок в Python и создал микросервис, используя flask-resplus. Отлично работает на моем компьютере и на сервере разработки, обслуживаемом http. У меня нет контроля над тем, где можно развернуть микросервис. В этом случае кажется, что он находится за балансировщиком нагрузки (не уверен в деталях), обслуживаемым через https.

Фактические ошибки, выдаваемые браузером: Не удается прочитать с сервера. Он может не иметь соответствующих настроек источника управления доступом.

Когда я проверяю инструменты сетевого разработчика, я вижу, что он не загружает swagger.json. Но проверяет это, используя: http://hostname/api/swagger.json вместо https.

Я погуглил и наткнулся на обсуждение этой проблемы. И это казалось исправлением, которое могло работать без необходимости менять библиотеку или конфигурации на сервере.

Однако все же я не мог заставить его работать.

Вот что у меня есть:

в файле апи:

api_blueprint = Blueprint('api', __name__, url_prefix='/api')
api = Api(api_blueprint, doc='/doc/', version='1.0', title='My api',
          description="My api")

в основном файле приложения:

from flask import Flask
from werkzeug.contrib.fixers import ProxyFix

from lib.api import api_blueprint

app = Flask(__name__)

app.wsgi_app = ProxyFix(app.wsgi_app)
app.register_blueprint(api_blueprint)

Также пробовал добавлять:

app.config['SERVER_URL'] = 'http://testfsdf.co.za' # but it dont look like is being considered

Используя flask-restplus==0.9.2,

Любое решение будет оценено, если мне не нужно настраивать контейнер, в котором будет развернута служба (я согласен с настройкой переменных среды), т.е. служба должна быть автономной. И если есть версия flask-resplus, которую я могу установить с помощью pip, в ней уже есть исправление, которое я могу оценить.

Большое спасибо, ребята,


person Mosd    schedule 27.11.2017    source источник


Ответы (2)


Переопределите класс API с параметром _scheme='https' в свойстве spec.

class MyApi(Api):
    @property
    def specs_url(self):
        """Monkey patch for HTTPS"""
        scheme = 'http' if '5000' in self.base_url else 'https'
        return url_for(self.endpoint('specs'), _external=True, _scheme=scheme)

api = MyApi(api_blueprint, doc='/doc/', version='1.0', title='My api',
        description="My api")
person Ilya Davydov    schedule 02.08.2018
comment
Спасибо, это сработало для меня при запуске моего приложения в производстве. Но когда я запускаю свое приложение локально, я получаю следующий ответ: «Не могу прочитать с сервера». У него могут отсутствовать соответствующие настройки источника управления доступом при вызове localhost:5000. Могу ли я в любом случае заставить это работать одинаково как в продукте, так и локально? - person Yogi Valani; 16.10.2018
comment
У меня есть твоя проблема. Просто используйте схему по умолчанию в локальной среде, см. отредактированный код. - person Ilya Davydov; 17.10.2018

Приведенное выше решение работает как шарм. Есть несколько вещей, которые вы должны проверить.

  1. Прежде чем применять исправление, убедитесь, что на вкладке chrome developertools -> Network каждый раз, когда вы перезагружаете страницу (на https-сервере), которая показывает пользовательский интерфейс swagger, вы получаете сообщение об ошибке смешанного содержимого для запроса swagger.json. .

  2. Решение в приведенном выше сообщении решает проблему при развертывании на https-сервере, но локально может вызвать проблему. Для этого вы можете использовать трюк с переменной среды.

  3. Установите пользовательскую переменную среды или любую переменную, которая уже есть на вашем https-сервере при развертывании вашего приложения. Перед применением решения проверьте наличие этой переменной среды, чтобы убедиться, что ваше приложение работает на сервере https.

Теперь, когда вы запускаете приложение локально, этот хак не будет применяться, и swagger.json будет обслуживаться через http, а на вашем сервере он будет обслуживаться через https. Реализация может выглядеть примерно так.

import os
from flask import url_for
from flask_restplus import Api

app = Flask( __name__)
if os.environ.get('CUSTOM_ENV_VAR'):
    @property
    def specs_url(self):
        return url_for(self.endpoint('specs'), _external=True, _scheme='https')
    Api.specs_url = specs_url
api = Api(app)
person Binoy S Kumar    schedule 17.06.2020
comment
Мне нравится использовать переменную FLASK_ENV, которая уже используется для среды flask. ссылка: flask.palletsprojects.com/en/1.1.x/api /?highlight=flask_env. Установите/экспортируйте FLASK_ENV=development для вашей схемы http. - person zerocog; 02.07.2021