Nginx

VueJS 向 Flask 發送 POST 失敗(CORS 請求被阻止)

  • August 8, 2019

我一直在關注這個vuejs 指南和這個燒瓶指南,將我的前端和後端託管在樹莓派上。

在我的前端,我有這個方法,它將 axios POST 發送到後端。

// path = http://127.0.0.1:5000/shift
// pin, port = 1-8 / SER1

sendByte(pin, port) {
 console.debug(`Setting ${pin} on ${port}`);
 // I'm adding the header to the payload directly
 const payload = {
   data: {
     pin,
     port
   },
   headers: {
     "Access-Control-Allow-Origin": "*",
     "Content-Type": "application/json"
   }
 };
 console.debug(payload);
 axios.post(this.paths.shift, payload);
}

但是我的後端沒有收到有效負載(因為 uwsgi.log 中沒有任何有效負載),而是在控制台中收到此錯誤:

11:53:38.551 new-submission event fired Setup.vue:52
11:53:38.578 Watch-Handler for submissions fired (localStorage updated) Setup.vue:33
11:53:42.312 Setting 1 on SER1 Visualization.vue:83
11:53:42.313
Object { pin: 1, port: "SER1" }
Visualization.vue:85
11:53:45.151 Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:5000/shift. (Reason: CORS request did not succeed). 2
11:53:45.154 Error: Network Error createError.js:16
11:53:46.351 Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:5000/togglePort. (Reason: CORS request did not succeed). 2
11:53:46.353 Error: Network Error createError.js:16

因為它與此錯誤最相關,所以這是我的 nginx.conf:

server {
   listen      80;
   server_name fire.com;
   charset utf-8;
   root    /var/www/fire-extinguish-visualizer/dist;
   index   index.html index.htm;    # Always serve index.html for any request
   location / {
       try_files $uri /index.html @fireFlask;
   }
   location /static {
       root /var/www/fire-extinguish-visualizer/dist/;
   }
   location @fireFlask {
       include uwsgi_params;
       add_header 'Access-Control-Allow-Origin' '*';
       add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
       add_header 'Access-Control-Allow-Headers' '*';
       # uwsgi_pass unix:/var/www/fire-extinguish-visualizer/server/uwsgi.sock;
       # uwsgi_pass 127.0.0.1:5000;
       uwsgi_pass uwsgi://localhost:5000;
   }
   error_log  /var/log/nginx/vue-app-error.log;
   access_log /var/log/nginx/vue-app-access.log;
}

我已經嘗試了許多配置和設置,但我無法讓它工作。

在所有這些嘗試之後,我不想發布我嘗試過的每個 nginx.conf 或 uwsgi.ini,但是為了更好地衡量,我的相關文件在這個 gist中。

我的問題是:

如何在 SENDER 和 RECEIVER 端正確設置 CORS 以避免此錯誤?

據我了解,完成以下操作後它應該可以工作:

  • Nginx 將 CORS 標頭添加到來自託管應用程序的 POST 請求
  • uWSGI 配置正確
  • Flask 應用程序已安裝 CORS 並允許跨域請求

那裡還有什麼?我現在只是對這個跨域錯誤感到困惑。

在 uwsgi.conf 中使用 http 時,我可以使用 curl 來獲得正確的響應:

pi@firepi:~ $ curl -X POST http://localhost:5000/togglePort -d '{"port":"SER1", "trigger":0}' -H 'Content-Type:
application/json'
{"status":"success"}
pi@firepi:~ $ curl -X POST http://localhost:5000/shift -d '{"port":"SER1", "pin":1}' -H 'Content-Type: application/json'
{"status":"success"}

嘗試帶有標題和來源的捲曲給出了這個:

pi@firepi:~ $ curl --include -X OPTIONS http://localhost:5000/togglePort -d '{"port":"SER1","trigger":0}' --header Access-Control-Request-Method:POST --header Access-Control-Request-Headers:Content-Type --header Origin:http://localhost:80
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Allow: OPTIONS, POST
Access-Control-Allow-Origin: http://localhost:80
Access-Control-Allow-Headers: Content-Type
Access-Control-Allow-Methods: DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT
Vary: Origin
Content-Length: 0

我也偶然發現了uwsgi-tools,但我真的不知道如何使用 uwsgi_curl 發送特定的 CORS 標頭。不過,這將有助於解決此問題,因為我可以縮小範圍。有什麼想法嗎?

由於我的程式碼/配置中的 3 個錯誤配置而發生此問題。

更正 #1

正如@Slytherin 在評論中建議的那樣,為了使 Nginx 正常工作,我需要將 POST 發送到正確的埠。在我的 Vue-App 中,我已經程式將 POST 直接發送到 Flask-App,這會導致 CORS 錯誤,因為 Nginx 無法添加適當的標頭。我通過修復路徑來修復它:

...
paths: {
       // This is a static Address. I later changed it to a hostname: firepi:80
       togglePort: "http://192.168.137.139:80/togglePort",
       shift: "http://192.168.137.139:80/shift"
     }
...

需要注意的是,當localhost作為地址使用時,瀏覽器實際上會指向它自己。因此,如果您在伺服器 X 上執行您的應用程序並從 PC A 訪問它,則 localhost 的路徑實際上將在 PC A 中解析,而不是在伺服器 X 中。因此,建議使用正確設置的主機名。

更正 #2

因為我的主要錯誤發生在問題 1(Nginx 埠)中,所以穩定地查看問題 2 是非常錯誤的。(CORS 配置)要啟用 CORS,我需要在Nginx 配置中添加正確的標頭,還需要配置我的 Flask-App 中的 CORS。對於 Flask,我只使用了預設值CORS(app)

在我的特殊情況下,我允許所有來源,因為此應用程序位於本地網路內,但在將應用程序連接到網際網路時,您應該明確限制此類訪問。

更正 #3

由於我將應用程序定向到埠 80 上的地址,因此我需要在 Nginx 中配置該連結:

location /togglePort {
       include uwsgi_params;
       uwsgi_pass unix:/var/www/fire-extinguish-visualizer/server/app_uwsgi.sock;
}
location /shift {
       include uwsgi_params;
       uwsgi_pass unix:/var/www/fire-extinguish-visualizer/server/app_uwsgi.sock;
}

引用自:https://serverfault.com/questions/977579