在某天写 bug 的时候,遇到了需要跨域的问题。
简单来说,就是我的网站是 waygc.net ,但我需要请求一个第三方网站,比如 github.com 上的资源。 这样做的目的是可以保持资源的动态更新。
比如,我要请求某个文件,这个问题件是某个库的组成部分,而这个库在不断更新中。 我为了保持和 github 同步,最直接的方式就是直接拉取 github 上的资源文件来用。 于是就涉及到了跨域问题。
但这个文件又不是 js ,也不是 json 、图片,所以没法直接通过 script 标签、img 标签来下载。 只能通过最原始的 ajax 下载来实现。
开始写代码:
$.get("https://github.com/something", (res) => {
console.log(res);
});
然后果不其然的得到了错误。
然后开始尝试其他的解决方案。
不过搜遍网上的各种方法,基本都没用,或者都有很大的限制。更进一步可以说纯前端的跨域解决就是个不可能的任务(?)
这里稍微盘点一下各种尝试过的解决方案。
<meta name="Access-Control-Allow-Origin" content="*" />
而从 MDN 的资料来看,这个标签的作用是让别人可以访问自己的资源的时候用,和我的要求正好相反。
通过 jsonp 的方式,确实可以直接跨域,但与此同时又来带一个问题:
jsonp 的返回值必须是一个 json 对象,如果返回的对象不是一个 json 对象(不管带不带“()”)
jsonp 的返回值都会无法解析,从而导致后续所有的操作都无法继续进行。
要配置,webpack,还要启动测试服务器,我就想要一个简单的可跨域的操作,还搞的这么复杂?
本来想去解析 chrome 的 allow-cors-access-control 插件的,但看到上千行的代码后,顿时就没了兴趣……
我就想搞个前端的跨域而已,还要启个服务器?
以后在厕所里蹲号刷手机的时候看到 nginx 的反向代理的时候想到,这应该可以,于是再次尝试之。
这么做的原理是:
我把要请求的资源当成自己的资源向服务器发送,然后让 nginx 来转发这个请求。 这样就可以完美避开浏览器上的跨域问题,也不用单独启动服务器,就是多配置一个 nginx 的事情,完美~
nginx 配置
server {
listen 80;
location ~ /request/(.+)$ {
proxy_pass https://github.com/$1/;
}
}
不过这样 nginx 会得到一个错误:
[error] 31198#31198: *1 no resolver defined to resolve github.com,
需要再在 http 里加入一条配置:
http {
resolver 8.8.8.8;
}
这件事在大约一年后有个后续,当时要处理高德地图的问题。
但高德地图通过 api 向高德请求数据需要 key 、安全密钥 这些乱七八糟的东西,如果把这些东西放在前端,拿就全暴露了,安全性荡然无存。
所以就想到里这里,从前端向自己的服务器请求一个 /amap
的接口,参数就是想要向高德发送的内容,在服务器上让 nginx 去拼接高德 的 key 和 安全密钥 就可以了。
server {
listen 80;
server_name 我的服务器;
# 自定义地图服务代理
location ~* ^/amap/(.*)$ {
set $args "$args&platform=JS&s=rsv3&logversion=2.0&key=高德key&jscode=高德安全密钥";
proxy_pass https://restapi.amap.com/$1?$args;
}
}