[Flask backend] record a cross domain experience of sadness

For the first time, the Python back-end interface was sent to the front-end after the Postman test. The front-end worked for a long time and said it was a cross domain problem. I wondered why the web page didn't work when Postman could pass. Was there a problem with the front-end code? The front-end boss explained that the Postman test could not find cross domain problems. Then I wrote an Ajax request and found that POST couldn't connect to the back end.

At first, I thought there was a problem with the Ajax request code, and I searched the Internet for various changes. What's the XHR Change the open () parameter to true, change a binding function for button, use the native Ajax request header, change the parsing function of json data, add COARS(app) to the back end, change the parameter, change the token... Anyway, all the methods that can be used have been used, and there is basically nothing that can be solved. Find someone in the group to help fix the bug, and even get cheated of 50 yuan...

Finally, the good thing is that we have finally found a solution. Here we record the solution and wake up the latecomers.

First, the page is a test page with only two request parameters, user_id and password, which can be easily requested on Postman:

However, the Ajax request reported an error:

Pay attention to the tips in the box. As long as you see this, don't think about others, just think about cross domain!! First post the source code of Ajax web page request (replace the ip and port with your own):

<!DOCTYPE html>
<html lang="zh_CN">
<head>
    <meta charset="utf-8">
    <title>Document</title>
</head>
<body>
    <p><input type="text" id="u" ></p>
    <p><input type="text" id="p"></p>
    <p><input type="button" value="Submit" id='btn'></p>

    <script type="text/javascript">
        var btn = document.getElementById('btn');
        btn.onclick=function() {
            var xhr=new XMLHttpRequest();
            var params = {'user_id': document.getElementById('u').value, 'password': document.getElementById('p').value}

            // Configuring Ajax objects
            xhr.open('post','http://119.3.230.94:9101/login/', true);
            // Send request header
            xhr.setRequestHeader("Content-type","application/json");
			// Send request body in json format
            xhr.send(JSON.stringify(params));
            xhr.onload=function() {
            	// Parse the response body in json format sent from the back end
                console.log(JSON.parse(xhr.responseText))
            }
        }
    </script>
</body>
</html>

The important thing is the modification of the back-end code, that is, how flash solves the corresponding problem of cross domain requests. First, summarize some common methods on the Internet (which may be useful for other programs, but not for me):

  1. Configure global routing using CORS function
from flask import Flask, request
from flask_cors import CORS

app = Flask(__name__)
CORS(app, supports_credentials=True, resources={r"/login/*": {"origins": "*"}})
  1. Use @ cross_ Orient configure interface routing
from flask import Flask, request
from flask_cors import cross_origin

app = Flask(__name__)


@app.route('/')
@cross_origin(supports_credentials=True)
def hello():
    name = request.args.get("name", "World")
    return f'Hello, {name}!'

Finally, I finally found a useful method for me, that is to use the standard response structure of flash to construct the response body, configure its own response header for the response body, and set the parameters of cross domain request in the response header!

Specifically, my original response body is constructed as follows:

data = {"user_id": id, "password": password}
return json.dumps(data), 200, {"ContentType": "application/json"}

Of course, this response method is not impossible, but it is not a standard flash response body, it is not very convenient for the construction of response headers, and many flash features are not supported. In order to better cross domain, special make is adopted_ Response to construct the response body:

from flask import make_response
------
data = {"user_id": id, "password": password}
res = make_response(jsonify(data))
res.status = "200"
# Important! Construct cross domain allowed response headers
res.headers["Access-Control-Allow-Origin"] = "*"
res.headers['Access-Control-Allow-Methods'] = "*"
res.headers['Access-Control-Allow-Headers'] = 'x-requested-with,content-type'
######################
return res

The most important thing is to construct a cross domain allowed response header, so that after each return function is constructed in this way, the front-end page can respond correctly!!

Keywords: Blockchain Back-end Ethereum Digital Currency

Added by tonbah on Wed, 02 Mar 2022 13:43:40 +0200