Flask CORS не работает при оперативном развертывании

#python-3.x #firebase #heroku #flask #cors

#python-3.x #firebase #heroku #flask #cors

Вопрос:

Я десятки часов пытался выяснить, почему приложение выдает ошибку 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 в свое серверное приложение и он отлично работает на локальном хостинге для тестирования. Как только я развертываю как интерфейс, так и серверную часть на серверах размещения, я получаю ошибку 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. Пожалуйста, не смейтесь над структурой кода, это первый раз, когда используется 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
  

Ответ №1:

попробуйте это:

 from flask_cors import cross_origin
  

затем добавьте декоратор @cross_origin() в свой маршрут api следующим образом

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

Комментарии:

1. HttpErrorResponse {заголовки: HttpHeaders, статус: 500, statusText: «ВНУТРЕННЯЯ ОШИБКА СЕРВЕРА», URL: » email-client-live.herokuapp.com/retrieve_email «, ok: false, …} Я предполагаю, что проблема с хостинговым сервером Heroku, потому что собираюсь api-client.herokuapp.com возвращает json, но api-client.herokuapp.com/retrieve_email выдает ошибку, упомянутую выше. Я пытаюсь получить электронные письма из gmail, используя IMAP, поэтому мне интересно, является ли проблемой проверка учетных данных (информация для входа).

2. Я также пытался получить доступ к api-client.herokuapp.com/retrieve_email URL через среду разработки выдает ту же ошибку. Хотя api-client.herokuapp.com/login отлично работает как в реальных средах, так и в средах разработки.

3. Tbh, я думаю, что декоратор @cross_origin вызывает больше проблем. Изменение маршрута возврата для / retrieve_email на jsonify({‘key’: ‘value’}) больше не работает (я тестировал это с Postman). Удаление декоратора устраняет проблему.

4. @ElonasMarkauskas, ошибка 500 — это что-то не так в ваших кодах, вы получили ошибку интервала, затем она выдает ошибку 500. Итак, я предлагаю вам проверить этот метод email_test.email_receive() 1st (одна из причин, которая может вызвать эту ошибку, заключается в том, что Gmail блокирует ваш сервер как доступ третьей стороны по соображениям безопасности). Что касается декоратора, я использую этот декоратор для своего проекта, и пока у меня нет никаких ошибок по этому поводу. Для jsonify это просто метод, который преобразует ваш ответ в формат json (например, json.dumps), но с соответствующим заголовком типа содержимого ‘application / json’ для использования с ответами json.

5. Хорошо, я посмотрю на код, я опубликую его, как только у меня будет такая возможность. У меня возникли проблемы с Gmail, блокирующим мое соединение и получение электронных писем.