精细结构

目录

记一次跨域的解决方案

在某天写 bug 的时候,遇到了需要跨域的问题。

简单来说,就是我的网站是 waygc.net ,但我需要请求一个第三方网站,比如 github.com 上的资源。 这样做的目的是可以保持资源的动态更新。

比如,我要请求某个文件,这个问题件是某个库的组成部分,而这个库在不断更新中。 我为了保持和 github 同步,最直接的方式就是直接拉取 github 上的资源文件来用。 于是就涉及到了跨域问题。

但这个文件又不是 js ,也不是 json 、图片,所以没法直接通过 script 标签、img 标签来下载。 只能通过最原始的 ajax 下载来实现。

开始写代码:

$.get("https://github.com/something", (res) => {
    console.log(res);
});

然后果不其然的得到了错误。
然后开始尝试其他的解决方案。

不过搜遍网上的各种方法,基本都没用,或者都有很大的限制。更进一步可以说纯前端的跨域解决就是个不可能的任务(?)
这里稍微盘点一下各种尝试过的解决方案。

1. 在网页头部加入标签

<meta name="Access-Control-Allow-Origin" content="*" />

而从 MDN 的资料来看,这个标签的作用是让别人可以访问自己的资源的时候用,和我的要求正好相反。

2. JSONP

通过 jsonp 的方式,确实可以直接跨域,但与此同时又来带一个问题:

jsonp 的返回值必须是一个 json 对象,如果返回的对象不是一个 json 对象(不管带不带“()”)
jsonp 的返回值都会无法解析,从而导致后续所有的操作都无法继续进行。

3. proxytable

要配置,webpack,还要启动测试服务器,我就想要一个简单的可跨域的操作,还搞的这么复杂?

4. 浏览器插件

本来想去解析 chrome 的 allow-cors-access-control 插件的,但看到上千行的代码后,顿时就没了兴趣……

5. 中间代理服务器

我就想搞个前端的跨域而已,还要启个服务器?
以后在厕所里蹲号刷手机的时候看到 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;
}

6. 后续

这件事在大约一年后有个后续,当时要处理高德地图的问题。
但高德地图通过 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;
        }
    }

参考资料