6

Info: for backend I'm using python with flask (for the moment it accepts http get methods) and for frontend I'm using html, css and javascript.

Problem: I'm trying to make a http request (first time I tried POST and then GET) but the browser did not allow me to do that: "Access to XMLHttpRequest at 'localhost:5000/test' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https.".

What another choices do I have? (I would like some simple choices, it is just a homework).

I've tried to make http POST and GET request. I've read that I cannot make http request from browser. I've read that I need (for example) an apache server. - too complicated, I need something more simple. I've tried: https://flask-cors.readthedocs.io/en/latest/

document.getElementById("btn").addEventListener('click', add);
function add()
{
    const url = "localhost:5000/test";
    const http = new XMLHttpRequest();
    http.open("GET", url);
    http.send();
    http.onreadystatechange=(e)=> {
        console.log(http.responseText)
    }
}
from flask import Flask
from flask_cors import CORS
from flask import request
from flask import jsonify
import json
import mysql.connector
import random
import string
import time

time.sleep(3)
app = Flask(__name__)

@app.route("/test")
def test():
    return "It's working"


if __name__ == "__main__":
    app.run(host='0.0.0.0', port=5000)

I expect that in the browser console to be printed message: "It's working", but I get the error: Access to XMLHttpRequest at 'localhost:5000/test' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https.

LE: Flask server is inside a docker container. Ports are mapped "5000:5000'.

2 Answers 2

5

If you are using same machine, you do not need to use flask-cors.

Update: As you are using Docker you can use flask-cors to handle CORS.

I found that the AJAX calls were not correct in your JS code. const url = "localhost:5000/test"; does not provide information on request protocol.

I followed these steps to run Flask application successfully using Docker and accessing the /test endpoint using JS outside Docker.

  • I updated AJAX request
  • Added Dockerfile to run Flask application inside Docker
  • Build and run the Dockerfile
  • Get the IP address of running Docker container.
  • Used the IP address in AJAX call in JS code which is outside Docker.

Folder structure:

.
├── backend.py
├── Dockerfile
├── readme.md
└── requirements.txt

requirements.txt:

Flask==1.0.2
Flask-Cors==3.0.7

Dockerfile:

FROM python:3
ENV PYTHONBUFFERED 1
RUN mkdir /code
WORKDIR /code
ADD requirements.txt /code/
RUN pip install -r requirements.txt
ADD . /code/
CMD ["python", "backend.py" ]

Build Docker file:

docker build -t flask-docker .

Run Docker:

docker run -p 5000:5000 flask-docker

* Serving Flask app "backend" (lazy loading)
* Environment: production
  WARNING: Do not use the development server in a production environment.
  Use a production WSGI server instead.
* Debug mode: off
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)

Get Docker container ID:

docker ps

CONTAINER ID        IMAGE                   COMMAND                CREATED             STATUS              PORTS                    NAMES
69cb7d5d243a        flask-docker            "python backend.py"    15 minutes ago      Up 15 minutes       0.0.0.0:5000->5000/tcp

Get Docker container IP address:

docker inspect --format '{{ .NetworkSettings.IPAddress }}' 69cb7d5d243a  

172.17.0.2

Use this IP address in AJAX request in HTML file:

<html>
<head>
  <title>Frontend</title>
</head>
<body>
  <div id="data"></div>
  <button type="button" id="btn">Grab data</button>
  <script type="text/javascript">
  document.getElementById("btn").addEventListener('click', add);
  function add()
  {
    const api_url = "http://172.17.0.2:5000/test";
    var xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function() {
      if (this.readyState == 4 && this.status == 200) {
        document.getElementById("data").append(this.responseText);
      }
    };
    xhttp.open("GET", api_url, true);
    xhttp.send();
  }
  </script>
</body>
</html>  

backend.py:

from flask import Flask, request, jsonify
from flask_cors import CORS


app = Flask(__name__)
CORS(app)    

@app.route("/test")
def test():
    return "It's working"    

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=5000)

Output:

frontend output

Sign up to request clarification or add additional context in comments.

5 Comments

I forgot to mention (and I'll edit the question right now). The flask server it's inside a docker container. So, they are not on the same machine theoreticaly.
share your docker configuration.
Here textsaver.flap.tv/lists/2k6f is a link to the config files (from terminal).
@BogdanCretu, updated the answer to facilitate Docker based Flask application.
Hehe, it’s working right now. What did I have to do was to include flask_cors (which I tried before) but another problem was (as you said before) my javascript request was wrong. There’s is not need for giving the container ip because the OS (or docker? or both?) can make the routing. (I saw that with postman (the url in postman was localhost:5000/test) and worked well). So, in my case, it's working with localhost:5000/test. Thank you, arsho!! ^_^
1

Add the following line below app = Flask(__name__):

CORS(app)

Check out flask-cors simple usage

3 Comments

It doesn't work. I forgot to mention (and I'll edit the question right now). The flask server it's inside a docker container.
LE: Yup, CORS + below javascript code it's working. Thank you, Parth Sharma!!
No problem @BogdanCretu :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.