前言
在部署项目的时候,突然发现前端的Axios
报了个AxiosError
,内容是Network Error
。记录这一次的解决过程。
背景
本来是源于这个项目:convert-windows-cursor-to-xcursor
在这里,我简单描述一下:
前端,我没有使用任何框架,所以直接使用link
引入axios.min.js
,然后在script
片段中直接请求:
1 2 3 4 5 6 7 8 9 10
| axios.post('http://www.sakebow.cn:40080/upload', formData, { headers: { 'Content-Type': 'multipart/form-data' } }) .then(function (response) { alert('好耶!上传好了!') monitorTask(response.data.task_id) }) .catch(function (error) { alert(`卧槽,怎么就因为${error}崩掉了啊……`) })
|
然后后端直接使用flask
简单接通一下:
1 2
| if __name__ == '__main__': app.run(host='0.0.0.0', port=40080)
|
本地测试通过,云服务器测试通过。
那就直接上:
1
| $ nohup gunicorn -b 0.0.0.0:40080 app:app > app.log 2>&1 &
|
直到这一步都是没问题的。
然后,我就心血来潮,趁着腾讯云的https
还能申请一年的时候,直接就拿下了一个免费的,于是将毫无框架的前端放在了443
端口上,也就是https
服务。
这不放还好,一放直接炸了。因为客户端的访问是基于https
的,但是在https
的访问过程中由axios
明文请求了http
,这个操作是不被浏览器所允许的,于是就报错了。
解决方案
其实解决方案也很简单,就是将index.html
中的明文http
请求修改为相对请求,这样,经过https
访问的浏览器就会自然而然地请求https
的接口。至于之后的事情,就交给proxy_pass
好了。
配置参考其实在库中的这个文件里面已经全部给出来了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| http { ... ##################### My Settings ##################### server { charset utf-8,gbk; listen 80; location / { root /usr/local/repo/cursor; index index.html; } location /api { proxy_pass http://127.0.0.1:40080/; expires off; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } # ----------------------------------------------------- # --------- Settings for Cloud Server (Https) --------- # ----------------------------------------------------- server { charset utf-8,gbk; listen 443 ssl; server_name www.example.cn; # edit here location / { root /usr/local/repo/cursor; index index.html; } location /api/ { proxy_pass http://127.0.0.1:40080/; expires off; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } ssl_certificate www/example.cn_bundle.crt; # edit here ssl_certificate_key www/example.cn.key; # edit here ssl_session_timeout 5m; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE; ssl_prefer_server_ciphers on; } ... }
|
这个部分可以写在nginx.conf
中,也可以将server
部分拆分成多个文件,然后通过include
的方式引入。
这样写的意思就是,我虽然访问了象征着https
的443
端口,并且按照location
中设定的root
获取到了代表主页面的index.html
信息,所有以/api/
结尾的请求,都将被proxy_pass
转发到象征http
的40080
端口,最终返回的结果也将从443
端口返回到客户端。
这种方法使得我们部署的任何服务,都将以index.html
所处的是http
的80
端口还是https
的443端口为标准。
最后,为了方便前端能够正确访问到40080
端口的服务,我们需要使用相对位置。
也就是说,请求最开始从443
进来,然后通过相对位置,axios
将依然通过https
访问服务。这个时候,如果我们配置了nginx
的server
,我们将通过这个server
把443
端口的请求转发到40080
端口。我们的请求从https
转移到了http
,但是axios
已经将数据转发到服务器后,属于axios
的请求过程就告一段落了,服务器内部的nginx
逻辑并不在axios
的管辖范围内。
于是,按照这个逻辑,我们的请求就成功的过了一遍flask
,然后通过https
返回出来了。