在https服务器

时间:2017-11-27 10:04:20

标签: python-3.x flask flask-restplus

我是python的新手,我使用flask-resplus创建了一个微服务。 在我的计算机和使用http服务的开发服务器上正常工作。 我无法控制微服务的部署位置。在这些情况下,它似乎是负载平衡器(不确定细节)的背后,与https一起提供。

浏览器给出的实际错误:无法从服务器读取。它可能没有适当的访问控制原点设置。

当我检查网络开发人员工具时,我发现它无法加载swagger.json。但是使用以下方法检查: http://hostname/api/swagger.json,而不是https。

我一直在谷歌搜索,我讨论了this问题。 this似乎是可以解决的问题,我不必更改服务器上的库或配置。

但是我仍然无法让它发挥作用。

这就是我所拥有的:

在api文件中:

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安装,那已经有一个修复,我可以欣赏。

非常感谢,

2 个答案:

答案 0 :(得分:4)

使用_scheme='https'属性中的spec选项覆盖API类。

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")

答案 1 :(得分:1)

以上解决方案的工作原理很吸引人。您应该检查几件事。

  1. 在应用此修复程序之前,请确保在您的 chrome developertools->网络标签中,无论何时重新加载显示摇摇欲坠的UI的页面(在https服务器中), swagger.json请求出错。

  2. 以上文章中的解决方案解决了在https服务器上部署时的问题,但在本地可能会出现问题。为此,您可以使用环境变量技巧。

  3. 设置自定义环境变量或在部署应用程序时https服务器上已经存在的任何变量。在应用解决方案之前,请检查该环境变量是否存在,以确保您的应用程序在https服务器中运行。

现在,当您在本地运行应用程序时,将不会应用此hack,并且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)