Vue与Express经NGINX通信异常及相关技术疑问求助
Hey Marek, let's break down your two questions and fix those frustrating issues step by step!
问题1:能不能移除Axios?
绝对不行!Axios(或者原生fetch、XMLHttpRequest)是前端浏览器发起HTTP请求的必要工具——Nginx作为反向代理服务器,它的作用是接收前端发送的请求、转发给后端Express服务,再把响应回传给前端。前端必须通过Axios这类工具发起请求,Nginx才有请求可以处理转发。
你的CONNECTION_REFUSED错误大概率是Axios的baseURL配置错误导致的:
- 如果你的
api.js里把baseURL设成了http://localhost:3000,那在浏览器中运行时,这个localhost指的是用户自己的本地电脑,而不是你的DigitalOcean服务器。浏览器会试图连接用户本地的3000端口,自然会被拒绝。
正确的Axios配置:
使用相对路径指向Nginx配置的代理路径:
// @/services/api.js import axios from 'axios' export default () => { return axios.create({ baseURL: '/api' // 相对路径,对应Nginx中配置的/api location }) }
这样当你调用api().get('projects')时,实际发起的请求是https://website.com/api/projects,这个请求会被Nginx捕获并转发到你的Express后端。
额外的Nginx路径修正:
你的location /api/配置里,proxy_pass末尾缺少斜杠,会导致路径转发错误。比如请求/api/projects会被转发到http://backend/api/projects,而你的Express后端路由是/projects,这会导致404。修改成:
proxy_pass http://backend/;
加上末尾斜杠后,Nginx会把/api/后面的路径拼到http://backend/后面,也就是/api/projects → http://backend/projects,完美匹配你的后端路由。
问题2:HTTPS前端与HTTP后端的CORS问题
你猜的完全正确!浏览器会严格阻止HTTPS页面发起HTTP请求(混合内容风险),再加上你当前的CORS头配置错误,双重因素导致了“CORS request did not succeed”错误。
解决方案:
不需要让前端直接请求HTTP后端
你的Nginx已经配置了HTTPS,前端通过HTTPS请求Nginx的/api路径,Nginx内部用HTTP转发到本地的Express服务(127.0.0.1:3000)。这个过程对浏览器完全透明——浏览器只和Nginx做HTTPS通信,不会接触到HTTP的后端,所以不会有混合内容问题。修正Nginx的CORS头配置
你当前配置的Access-Control-Allow-Origin是http://localhost:8080和http://localhost:3000,这是开发环境的地址,但生产环境中前端的请求来源是https://website.com,这些头完全无效,反而会触发CORS错误。实际上,因为前端和API请求的是同一个域名、同一个协议、同一个端口,属于同源请求,根本不需要设置CORS头!可以直接删除所有
add_header 'Access-Control-Allow-*'的配置。如果你后续需要支持跨域调用API,可以动态匹配请求来源:
add_header 'Access-Control-Allow-Origin' "$scheme://$host" always;Vue单页应用的Nginx补充配置
你的location /配置里try_files $uri $uri/ =404;会导致Vue页面刷新时404,因为Nginx找不到对应路由的静态文件,需要把所有路由请求转发到index.html由Vue处理:location / { try_files $uri $uri/ /index.html; }
修正后的完整Nginx配置片段:
upstream backend { server 127.0.0.1:3000; keepalive 8; } server { listen 443 ssl default_server; listen [::]:443 ssl default_server; root /var/www/html/PersonalWebsite/frontend/dist; index index.html index.htm index.nginx-debian.html; server_name website.com www.website.com; ssl_certificate <link-to-cert>; ssl_certificate_key <link-to-key>; include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot # Redirect HTTP to HTTPS (Certbot配置无需修改) if ($scheme != "https") { return 301 https://$host$request_uri; } # managed by Certbot location / { try_files $uri $uri/ /index.html; # 适配Vue单页应用路由 } location /api/ { proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://backend/; # 修正路径转发的斜杠 } }
内容的提问来源于stack exchange,提问作者MarekCze

