background
There is a JS app serving at 127.0.0.1:8080, which refers some API serving at 127.0.0.1:5000 by a Flask app. [See FlaskCode]
When I open this js app in Chrome, first request work well and the second request ends with CORS problem, [see ChromeDebug1].
Additionally, I found this 'OPTIONS' is response as 405 (method not allow) in Flask output, and the output from flask_cors is not same like first request. [see FlaskOut].
I'm a newbee in FE and python, so if it is stupid bug, please let me know.
question
It seems that flask_cors works only once in my code, but what's wrong?
Look at the difference of first req and second req, seems that second reponse for 'OPTIONS' do not have headers
("Access-Control-Allow-Origin", "*")
?why firest request not have log like
flask_cors.extension:Request
appendix
FlaskCode
# -*- coding: UTF-8 -*-
from flask import Flask
from flask import Response
from flask_cors import CORS, cross_origin
import logging
import json
app = Flask(__name__)
CORS(app, supports_credentials=True)
demoDataPath="xxx"
@app.route("/yd/pass-through/get-examination", methods=['POST'])
@cross_origin()
def getexamination():
logging.getLogger('demo2').info('into getexamination')
response = {}
response["code"]=0
response["message"]="good end"
f = open(demoDataPath "/rsp4getexamination.json", "r")
response["data"]= json.loads(f.read())
return Response(json.dumps(response), mimetype='application/json', status=200)
@app.route("/yd/pass-through/report-config", methods=['POST'])
@cross_origin()
def getconfig():
logging.getLogger('demo2').info('into getconfig')
response = {}
response["code"]=0
response["message"]="good end"
f = open(demoDataPath "/rsp4getreportconfig.json", "r")
response["data"]= json.loads(f.read())
return Response(json.dumps(response), mimetype='application/json', status=200)
if __name__ == '__main__':
logging.getLogger('flask_cors').level = logging.DEBUG
logging.getLogger('werkzeug').level = logging.DEBUG
logging.getLogger('demo2').level = logging.DEBUG
app.logger.setLevel(logging.DEBUG)
logging.info("app run")
app.run(debug=True, threaded=True, port=5001)
ChromeDebug1
FlaskOut
DEBUG:flask_cors.core:CORS request received with 'Origin' http://127.0.0.1:8080
DEBUG:flask_cors.core:The request's Origin header matches. Sending CORS headers.
DEBUG:flask_cors.core:Settings CORS headers: MultiDict([('Access-Control-Allow-Origin', 'http://127.0.0.1:8080'), ('Access-Control-Allow-Headers', 'content-type, traceid, withcredentials'), ('Access-Control-Allow-Methods', 'DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT'), ('Vary', 'Origin')])
DEBUG:flask_cors.extension:CORS have been already evaluated, skipping
INFO:werkzeug:127.0.0.1 - - [21/Apr/2022 20:33:36] "OPTIONS /yd/pass-through/report-config HTTP/1.1" 200 -
[2022-04-21 20:33:36,736] INFO in demo2: into getconfig
INFO:demo2:into getconfig
DEBUG:flask_cors.core:CORS request received with 'Origin' http://127.0.0.1:8080
DEBUG:flask_cors.core:The request's Origin header matches. Sending CORS headers.
DEBUG:flask_cors.core:Settings CORS headers: MultiDict([('Access-Control-Allow-Origin', 'http://127.0.0.1:8080'), ('Vary', 'Origin')])
DEBUG:flask_cors.extension:CORS have been already evaluated, skipping
INFO:werkzeug:127.0.0.1 - - [21/Apr/2022 20:33:36] "POST /yd/pass-through/report-config HTTP/1.1" 200 -
DEBUG:flask_cors.extension:Request to '/yd/pass-through/get-examination' matches CORS resource '/*'. Using options: {'origins': ['.*'], 'methods': 'DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT', 'allow_headers': ['.*'], 'expose_headers': None, 'supports_credentials': True, 'max_age': None, 'send_wildcard': False, 'automatic_options': True, 'vary_header': True, 'resources': '/*', 'intercept_exceptions': True, 'always_send': True}
DEBUG:flask_cors.core:CORS request received with 'Origin' http://127.0.0.1:8080
DEBUG:flask_cors.core:The request's Origin header matches. Sending CORS headers.
DEBUG:flask_cors.core:Settings CORS headers: MultiDict([('Access-Control-Allow-Origin', 'http://127.0.0.1:8080'), ('Access-Control-Allow-Credentials', 'true'), ('Vary', 'Origin')])
DEBUG:flask_cors.extension:CORS have been already evaluated, skipping
INFO:werkzeug:127.0.0.1 - - [21/Apr/2022 20:33:36] "{"examinationOID":"61e8d2248373a7329e12f29b"}OPTIONS /yd/pass-through/get-examination HTTP/1.1" 405 -
CodePudding user response:
I solve my problem with another "bug" like following. And I still have no idea why my code not work as flask_cors document saied. If you have better solution or advice, please let me know.
@app.after_request
def add_headers(response):
response.headers.add('Content-Type', 'application/json')
response.headers.add('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS')
response.headers.add('Access-Control-Allow-Headers', 'content-type, traceid, withcredentials')
response.status=200
logging.getLogger('demo2').info('into add_headers')
return response
CodePudding user response:
The problem appears to be here:
INFO:werkzeug:127.0.0.1 - - [21/Apr/2022 20:33:36] "{"examinationOID":"61e8d2248373a7329e12f29b"}OPTIONS /yd/pass-through/get-examination HTTP/1.1" 405 -
Compare that to:
INFO:werkzeug:127.0.0.1 - - [21/Apr/2022 20:33:36] "OPTIONS /yd/pass-through/report-config HTTP/1.1" 200 -
It is trying to use an invalid HTTP method of {"examinationOID":"61e8d2248373a7329e12f29b"}OPTIONS
instead of just plain OPTIONS
.
It seems like something is corrupting your CORS headers and confusing Chrome into doing that. A likely source of that would be the Flask-CORS configuration. Is there some setup elsewhere that you haven't shown us? Or is it just using default configuration?
If it is just default, then it would help to see the Javascript code running in Chrome - that might be causing the corrupted method from the first request to the second.
Also, in your chrome dev tools screenshot, you are filtering on 'XHR' - that won't show the OPTIONS requests which will help you figure out what's going wrong. They are shown under 'Other'.