Mi sitio web tiene un servidor separado para el front-end y el back-end, por lo que mi servidor back-end necesita abrir permisos CORS para que el front-end pueda solicitarle datos.
Estoy usando Flask-Cors con éxito en el desarrollo, pero no funciona cuando lo implemento en producción. (tenga en cuenta que he mirado otras preguntas de frasco-cors en SO, pero ninguna de ellas se ajusta a mi situación)
Aquí está el código relevante que está trabajando en desarrollo:
# 3rd party imports import flask from flask import Flask, request, redirect, send_from_directory, jsonify from flask_cors import CORS # Create the app app = Flask(__name__) CORS(app, origins=[ 'http://localhost:5001', ]) # Define the routes @app.route('/') def index(): # no CORS code was necessary here app.logger.info(f'request is: {flask.request}')
Lo que he probado:
'http://162.243.168.182:5001'
a la lista CORS no es suficiente para resolver el problema, aunque entiendo que debería estar allí.'*'
para permitir TODOS los orígenes tampoco funciona. (¡muy sospechoso!) Tenga en cuenta que estoy usando un contenedor Docker, por lo que mi entorno entre desarrollo y producción es casi idéntico. Pero lo que es diferente es que estoy en un servidor diferente y modifiqué el front-end para enviar la solicitud a la nueva dirección IP (lo que resultó en el famoso “Access-Control-Allow-Origin” header missing
el error CORS).
Ahora me pregunto si al objeto de flask.request
de matraz le falta información, y esto hace que Flask-Cors no envíe el encabezado Access-Control-Allow-Origin como se supone que debe hacerlo. ¡Puedo proporcionar esa información de registro si cree que sería útil!
El Dockerfile que estoy usando en PROD es:
# base image FROM tiangolo/uwsgi-nginx-flask:python3.8-2020-12-19 # install deps RUN pip3 install ediblepickle==1.1.3 # RUN pip3 install flask==1.1.2 # pre-installed on tiangolo/uwsgi-nginx-flask RUN pip3 install flask-cors==3.0.9 RUN pip3 install numpy==1.19.2 RUN pip3 install scipy==1.5.2 RUN pip3 install pandas==1.1.2 RUN pip3 install networkx==2.5 # pull in files for deployment COPY ./app /app # Note that there is no CMD to run because the CMD set in the base image is what we already wanted. As long as the Flask app is called `app`, the python file is named `main.py`, the parent directory is named `app`, and that same directory gets copied into `/app`, then the base image is designed to make our app work out-of-the-box.
y el comando que uso para iniciarlo es:
docker build -t mvlancellotti/tennis-backend:prod -f prod.Dockerfile . && docker run --rm -p 5000:80 --name tennis-backend-container mvlancellotti/tennis-backend:prod
Al ingresar al directorio /app
del contenedor, se encuentra el archivo uwsgi.ini
con contenido:
[uwsgi] module = main callable = app
que parece funcionar, y el archivo /etc/nginx/nginx.conf
tiene contenido:
user nginx; worker_processes 1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; keepalive_timeout 65; include /etc/nginx/conf.d/*.conf; } daemon off;
y el archivo /etc/nginx/conf.d/nginx.conf
tiene contenido:
server { listen 80; location / { try_files $uri @app; } location @app { include uwsgi_params; uwsgi_pass unix:///tmp/uwsgi.sock; } location /static { alias /app/static; } }
La cuestión es que es el servidor del que está solicitando recursos el que debe tener el encabezado CORS (que sea serverA
), no el servidor que requiere archivos remotos ( serverB
). Si el servidor NGINX
serverA
Apache2
, puede usar esto para agregar el encabezado CORS a las respuestas:
NGINX :
add_header Access-Control-Allow-Origin *; # or add_header Access-Control-Allow-Origin serverB;
apache2 :
Header set Access-Control-Allow-Origin "*" # or Header set Access-Control-Allow-Origin "serverB"
Lo anterior significa "permitir * o serverB obtener recursos de este servidor (serverA)" .
Para cualquier persona nueva en CORS, recomiendo estas dos ( 1 , 2 ) lecturas cortas de Mozilla. Creo que son geniales para explicar los conceptos básicos.
Preferiría agregar un comentario, pero aún no hay suficientes representantes.
Nginx add_header no funcionará para los códigos de error.
Además, cuando reciba algún tipo de error (400, 500, 502, etc.), faltará el encabezado. Y el navegador le mostrará CORS, pero no importa, algo salió mal en otro lugar. Es común perder mucho tiempo por esto...
Accedí a su aplicación (lo siento si no se menciona que lo haga). Se carga y algunas opciones de filtro dan como resultado 502 y el navegador dirá: ¡Oh, CORS! Pero parece que algo está muriendo y regresando.
Información sobre add_header y errores: https://serverfault.com/questions/431274/nginx-services-fails-for-cross-domain-requests-if-the-service-returns-error