在部署项目的时候,突然发现前端的Axios
报了个AxiosError
,内容是Network Error
。记录这一次的解决过程。
本来是源于这个项目:convert-windows-cursor-to-xcursor
在这里,我简单描述一下:
前端,我没有使用任何框架,所以直接使用link
引入axios.min.js
,然后在script
片段中直接请求:
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
简单接通一下:
if __name__ == '__main__':
app.run(host='0.0.0.0', port=40080)
本地测试通过,云服务器测试通过。
那就直接上:
$ 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
好了。
配置参考其实在库中的这个文件里面已经全部给出来了:
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
返回出来了。