I have a problem with my api python using flask. When I try to access api from view, the browser says "Access to fetch at 'http://127.0.0.1:8859/api/calculadora' from origin 'http://127.0.0.1:5500' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled."
My api uses blueprints for endpoints. I have tried to solve the problem using flask-cors but it has not worked for me. (With Postman work correctly)
Project's structure: Project's structure
My code is the following:
main.py:
from flask import Flask , jsonify , request
from flask_cors import CORS, cross_origin
from dotenv import load_dotenv
from app.routes.auth import routesAuth
from app.routes.calculadora import calculadora_blueprint
app = Flask(__name__)
CORS(app, support_credentials=True)
app.register_blueprint(routesAuth, url_prefix="/api")
app.register_blueprint(calculadora_blueprint, url_prefix="/api")
if __name__ == "__main__":
load_dotenv()
app.run(None , 8859 , True)
calculadora.py:
from flask import Blueprint , request , Flask
from flask_cors import cross_origin , CORS
from app.function_jwt import validarToken
from app.models.Hipoteca import Hipoteca
from app.models.HipotecaDTO import HipotecaDTO
from app.models.Simulacion import Simulacion
from app.services.impl.HipotecaFijaServicio import HipotecaFijaServicio
from app.services.impl.HipotecaVariableServicio import HipotecaVariableServicio
from app.services.impl.SimulacionServicio import SimulacionServicio
calculadora_blueprint = Blueprint("calculadora_blueprint", __name__)
hipotecaFijaServicio = HipotecaFijaServicio()
hipotecaVariableServicio = HipotecaVariableServicio()
simulacionServicio = SimulacionServicio()
@calculadora_blueprint.before_request
def validar_token_middleware():
print(request.headers['Authorization'].split(" ")[1])
token = request.headers['Authorization'].split(" ")[1]
return validarToken(token,False)
@calculadora_blueprint.route("/calculadora", methods=["POST"])
@cross_origin(supports_credentials=True)
def calculadora():
print(request.headers['Authorization'].split(" ")[1])
# Almacenar el JSON recibido en un objeto Hipoteca
print(type(request.json['capitalInmueble']))
hipoteca = Hipoteca(request.json['totalIntereses'], request.json['capitalInmueble'],
request.json["capitalAportado"] , request.json["prestamo"] , request.json["cuota"],
request.json["plazo"] , request.json["plazoRestante"] , request.json["tasaInteres"],
request.json["tipoInteres"] , request.json["fechaNacimiento"] , request.json["ahorros"],
request.json["nomina"],request.json["otrosPrestamos"], request.json["esPrimeraVivienda"] )
simulacion = Simulacion(None,None,None)
simulacionServicio.generarHipoteca(hipoteca,simulacion)
porcentaje = simulacionServicio.calcularProbabilidad(simulacion)
hipoteca.amortizaciones = list()
if request.json["tipoInteres"] == "fijo":
hipotecaFijaServicio.calcularAmortizaciones(hipoteca)
print("cuota" str(hipoteca.cuota))
else:
hipotecaVariableServicio.calcularAmortizaciones(hipoteca)
response = HipotecaDTO(hipoteca,porcentaje)
return response.toJson()
fetch on js:
fetch('http://127.0.0.1:8859/api/calculadora',{
method: "POST",
body: JSON.stringify(s),
headers: {
"Content-Type": "application/json",
"Authorization" : "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6Ik1hcmNvcyIsInBhc3N3b3JkIjoxMjMsImV4cCI6MTY1NzcxNTM2Nn0.CyYX0X11ilUD8Rj-JI4Tb6ri1gb6n9HH_hsZKseA5BE"
}
})
.then(res => res.json())
.then(data => {
console.log(data.porcentaje)
imprimirTabla(data.hipoteca.amortizaciones);
imprimirTarjetas(data)
})
.catch(err => console.log(err))
EDIT 1
I found the error but I can't fix it. If I remove the middleware, it works perfectly.But I need it to validate the JSON web token
calculadora.py:
@calculadora_blueprint.before_request
def validar_token_middleware():
print(request.headers['Authorization'].split(" ")[1])
token = request.headers['Authorization'].split(" ")[1]
return validarToken(token,False)
CodePudding user response:
I usually use CORS in the following way
from flask_cors import CORS
app = Flask(__name__)
cors = CORS(app, resources={r"/*": {"origins": "*"}})
The asterisk "*" is a wildcard, so using it will allow access to the defined endpoint from any origin. If you want only access to 127.0.0.1:8859 to be allowed, try using the following:
cors = CORS(app, resources={r"/api/calculadora": {"origins": "127.0.0.1:8859"}})
The documentation of how to use CORS with Flask can be seen from here
CodePudding user response:
The Flask app you posted runs on port 8859:
if __name__ == "__main__":
load_dotenv()
app.run(None , 8859 , True)
Then you get:
"Access to fetch at 'http://127.0.0.1:8859/api/calculadora' from origin 'http://127.0.0.1:5500' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin'
Are you using an other Flask application on port 5500, as reverse proxy? In that case it is the one that needs CORS clearance.
When you reach the webapp on :5500 through the browser and it fetches from :8859, the browser complains that the webapp on :5500 doesn't have CORS clearance. Instead, when you reach :8859 through the Postman server, there is no browser involved and so no CORS complain. More on CORS.
Also, it's not safe to post bearer tokens.