【问题标题】:Flask CORS not working on live deploymentFlask CORS 无法进行实时部署
【发布时间】:2019-08-03 11:26:45
【问题描述】:

我已经挣扎了几十个小时,试图弄清楚为什么应用程序会产生 CORS(跨源资源共享)错误

Access to XMLHttpRequest at 'https://api-client.herokuapp.com/retrieve_email' from origin 'https://front-application.firebaseapp.com' has been blocked by 
CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

虽然我已将 CORS 添加到我的后端应用程序中,并且可以在 localhost 上完美运行以进行测试。将前端和后端都部署到托管服务器后,我会收到 CORS 错误。更有趣的是,它仅适用于 /retrieve_email 路径,但适用于 login - 虽然两条路径都需要 CORS。 / 路径可以正常工作,它会显示其中的 JSON,我还使用 Postman 对其进行了测试。

from flask import Flask, jsonify, request
from flask_cors import CORS
from email_receive import EmailReceive
from email_send import EmailSend


app = Flask(__name__)
CORS(app)

email_test = EmailReceive()


@app.route('/', methods=['GET'])
def index():
    return jsonify({'key': 'value'})


@app.route('/retrieve_email', methods=['GET'])
def retrieve_email():
    if request.method == 'GET':
        email_test.email_receive()
        return jsonify(email_test.get_email_data())


@app.route('/login', methods=['POST', 'GET'])
def login():
    if request.method == 'POST':
        data = request.get_json()
        email_test.set_credentials(data)
        return jsonify(data)
    elif request.method == 'GET':
        return jsonify(email_test.get_email_data())


@app.route('/send_email', methods=['POST', 'GET'])
def send_email():
    sending = EmailSend()
    if request.method == 'POST':
        data = request.get_json()
        sending.set_information(data)
        sending.email_send()
        return jsonify(data)
    elif request.method == 'GET':
        return jsonify({'key': 'value'})


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

以上是我使用 CORS 的代码的 sn-p。请不要嘲笑代码的结构,这是第一次使用 API 并使用 GET 和 POST 请求。前端(Angular)托管在 Firebase 上,后端(Flask)托管在 Heroku 上。

编辑1:我跑heroku logs --tail,基本上只是通过终端查看一些日志,以下是我得到的:

2019-03-14T19:03:35.999761+00:00 app[web.1]: [2019-03-14 19:03:35,999] ERROR in app: Exception on /retrieve_email [GET]
2019-03-14T19:03:35.999772+00:00 app[web.1]: Traceback (most recent call last):
2019-03-14T19:03:35.999774+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.7/site-packages/flask/app.py", line 2292, in wsgi_app
2019-03-14T19:03:35.999776+00:00 app[web.1]: response = self.full_dispatch_request()
2019-03-14T19:03:35.999778+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.7/site-packages/flask/app.py", line 1815, in full_dispatch_request
2019-03-14T19:03:35.999779+00:00 app[web.1]: rv = self.handle_user_exception(e)
2019-03-14T19:03:35.999780+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.7/site-packages/flask_cors/extension.py", line 161, in wrapped_function
2019-03-14T19:03:35.999782+00:00 app[web.1]: return cors_after_request(app.make_response(f(*args, **kwargs)))
2019-03-14T19:03:35.999783+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.7/site-packages/flask/app.py", line 1718, in handle_user_exception
2019-03-14T19:03:35.999785+00:00 app[web.1]: reraise(exc_type, exc_value, tb)
2019-03-14T19:03:35.999787+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.7/site-packages/flask/_compat.py", line 35, in reraise
2019-03-14T19:03:35.999790+00:00 app[web.1]: raise value
2019-03-14T19:03:35.999791+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.7/site-packages/flask/app.py", line 1813, in full_dispatch_request
2019-03-14T19:03:35.999793+00:00 app[web.1]: rv = self.dispatch_request()
2019-03-14T19:03:35.999794+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.7/site-packages/flask/app.py", line 1799, in dispatch_request
2019-03-14T19:03:35.999796+00:00 app[web.1]: return self.view_functions[rule.endpoint](**req.view_args)
2019-03-14T19:03:35.999798+00:00 app[web.1]: TypeError: decorator() missing 1 required positional argument: 'f'
2019-03-14T19:03:36.001321+00:00 app[web.1]: 10.45.158.146 - - [14/Mar/2019:19:03:35 +0000] "GET /retrieve_email HTTP/1.1" 500 291 "-" "PostmanRuntime/7.6.0"
2019-03-14T19:03:36.063632+00:00 heroku[router]: at=info method=GET path="/retrieve_email" host=email-client-live.herokuapp.com request_id=3dd5bc4a-0f57-4a82-b5f7-1bcccc64f263 fwd="73.210.197.125" dyno=web.1 connect=1ms service=73ms status=500 bytes=488 protocol=https

以下是 email_receive() 函数的代码:

import email
import email.header
import imaplib
import sys


class EmailReceive:
    imap_host = ''
    imap_user = ''
    imap_pass = ''

    email_package = []

    def __init__(self):
        self.imap_host = 'imap.gmail.com'
        self.imap_user = 'xxxxxxxx@gmail.com'
        self.imap_pass = 'xxxxxxxxxx'

    def set_credentials(self, data):
        self.imap_user = data['email']
        self.imap_pass = data['password']

    def email_receive(self):
        self.email_package = []
        email_instance = imaplib.IMAP4_SSL(self.imap_host)

        try:
            print(self.imap_user, self.imap_pass)
            rv, data = email_instance.login(self.imap_user, self.imap_pass)
        except imaplib.IMAP4.error:
            print('[*] email_receive.py: LOGIN FAILED')
            sys.exit(1)

        print(rv, data)

        rv, data = email_instance.list()
        if rv == 'OK':
            print('Mailboxes: ')
            print(data)

        rv, data = email_instance.select('Inbox')
        if rv == 'OK':
            print('Processing mailbox...')
            print(data)

        rv, data = email_instance.search(None, 'ALL')
        if rv != 'OK':
            print('[*] email_receive.py: No messages found!')
            return

        for num in data[0].split():
            rv, data = email_instance.fetch(num, '(RFC822)')
            if rv != 'OK':
                # print('[*] email_receive.py: ERROR getting message', num)
                return

            # print(data[0][1])

            message = email.message_from_bytes(data[0][1])
            subject = email.header.make_header(email.header.decode_header(message['Subject']))
            # print(message.keys())
            message_id = message['Message-ID']

            # print(header)
            sender = message['From']

            for part in message.walk():
                if part.get_content_type() == 'text/html':
                    self.email_package.append({'body': part.get_payload(decode=True).decode('utf-8'),
                                               'subject': str(subject),
                                               'from': str(sender),
                                               'messageid': str(message_id)})

    def get_email_data(self):
        return self.email_package

【问题讨论】:

    标签: python-3.x firebase heroku flask cors


    【解决方案1】:

    试试这个:

    from flask_cors import cross_origin
    

    然后像这样将 @cross_origin() 装饰器添加到您的 api 路由中

    @app.route('/', methods=['GET'])
    @cross_origin()
    def index():
        ...
    

    【讨论】:

    • HttpErrorResponse {headers: HttpHeaders, status: 500, statusText: "INTERNAL SERVER ERROR", url: "email-client-live.herokuapp.com/retrieve_email", ok: false, ...} 我假设有问题托管服务器 Heroku,因为转到 api-client.herokuapp.com 会返回 json,但 api-client.herokuapp.com/retrieve_email 会出现上述错误。我正在尝试使用 IMAP 从 gmail 检索电子邮件,所以我想知道是否凭据验证(登录信息是问题)。
    • 我也尝试通过开发环境访问 api-client.herokuapp.com/retrieve_email URL,它产生了同样的错误。尽管 api-client.herokuapp.com/login 在实时和开发环境中都可以正常工作。
    • Tbh,我认为 @cross_origin 装饰器会导致更多问题。通过将 /retrieve_email 路由的返回更改为 jsonify({'key': 'value'}) 不再起作用(我用 Postman 对其进行了测试)。删除装饰器可以解决问题。
    • @ElonasMarcauskas,错误 500 是你的代码中有问题,你得到一个间隔错误,然后它抛出错误 500。所以我建议你第一次检查这个 email_test.email_receive() 方法(原因之一可能导致此错误的原因是 Gmail 出于安全原因阻止您的服务器作为第三方访问)。至于装饰器,我在我的项目中使用了这个装饰器,到目前为止我还没有遇到任何错误。对于 jsonify ,它只是一种将您的响应转换为 json 格式(如 json.dumps)但具有适当内容的方法-type header 'application/json' 用于 json 响应。
    • 好的,我会看代码,有机会我会发布它。我一直遇到 Gmail 阻止我的连接和检索电子邮件的问题。
    猜你喜欢
    • 2018-08-28
    • 1970-01-01
    • 2023-03-27
    • 2014-01-08
    • 2021-10-27
    • 2020-06-30
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多