【浏览器】不求别人,用nginx反向代理就能搞跨域

面试遇坑

面试官: 你知道跨域有什么解决办法吗?神仙朱:JSONP 或者 后端修改相应头部 Accept-Control-Allow-Origin ??面试官:看你还用过 nginx 啊,不知道 nginx 可以反向代理解决跨域吗 ?

我心想还有这种操作 ??于是我很自信地回答他我不知道

素来我是遇到问题一定要解决的,没有什么东西可以一直困扰我。于是上网查了大量资料(一两篇文章),然后就尝试配置了一下 nginx ,最后真的解决了!!

现在我就来做一份自己的总结!

关键词

先来把几个关键知识点理一下

跨域

浏览器的同源策略 导致跨域! 注意是浏览器,只有在浏览器才存在有跨域。也就是说 服务器上不存在 跨域 的说法。所以才存在今天使用 服务器代理解决跨域的方法。

跨域的请求过程

跨域请求一般浏览器是可以发送跨域请求的,只是响应被拦截了。而 chrome 下会先发一个 options 请求去询问浏览器是否可以跨域,并且对这个请求结果进行缓存。如果 options 请求得到 跨域不允许,那么下一次跨域的时候不会再发送新的 options 请求 ,而是直接报跨域错误。

代理

正向代理

正向代理是隐藏客户端,服务器不知道真正的请求人。

比如你想访问某个网站,但是没有直接去访问,而是通过一个 代理服务器去访问 这个网站,利用代理服务器帮你发送请求,再把请求返回的信息转发给你。

上面的过程中,那个网站的服务器根本不知道到底是谁访问我。那么就达到了隐藏客户端的目的,这就是正向代理。

应用

科学上网:在国外部署代理服务器,通过这个代理服务器 实现代发请求,就可以科学上网

反向代理

反向代理 是隐藏服务器。客户端不知道真正的服务人。因为服务器会自动分配服务你的服务器,而你不知道真正给你提供服务的是谁。

比如我们访问淘宝,淘宝的服务器有很多。当我们访问淘宝的时候,淘宝服务器会将我们的请求转发给其他服务器。这时,淘宝服务器实现的功能就是 反向代理。

nginx 反向代理解决跨域

配置 window nginx 来测试一下

安装 nginx

访问官网下载:

选择 window 版本比如 nginx/Windows-1.12.2

下载成功,解压到某个文件夹,比如 D:/nginx

ok

启动 nginx

Ctrl+R 打开 CMD

进入到刚刚解压的文件夹

运行命令 ./nginx.exe

正常情况下,启动成功没有任何提示

配置 nginx

进入到解压的文件夹

比如D:/nginx进入 conf 文件夹,看到nginx.conf 就是配置文件,打开它,

修改端口

原来nginx 的端口是80,不过window 下 80端口可能被 System 占用了,所以我们换一个端口 ,比如是 8089

配置服务器请求匹配路径

在 (location / )后面加上另一个自定义路径配置这里我的路径是 /ho/ 也就是说如果我发送的请求中带有 ho ,那么就会匹配成功。比如 发送请求是 

:8089/ho/xxxx

里面包含 ho,所以匹配成功

12345678910111213# 这是原有的,只是为了找个对比位置location / {    root   html;    index  index.html index.htm;}# 这是新增的location /ho/ {    rewrite ^.+ho/(.*)$ /$1 break;    proxy_pass https://jingyan.baidu.com/ ;}

下面照着上面的配置来详细说明一下

rewrite

rewrite 的组要功能是实现RUL地址的重定向,就是进行 URL重写。我们的目的是去掉域名和匹配的路径,保留url正确的api路径这里使用了一个正则去匹配URL,/^.+ho/(.*)$/,正则不解释了。

举例

假设我们现在要在本地网页localhost通过 ajax 访问一个接口?method=getLog&likeNum=&type1423=

一般情况下,这是会跨域的而我们的目的就是想可以通过本地网页成功访问服务器接口!!所以先在本地构建一个接口,通过这个接口去转发到真正的接口上去!!!!:8089/ho/asyncreq/log?method=getLog&likeNum=&type1423=

回到nginx配置上来,看到 rewrite 设置为 ^.+ho/(.*)$ /$1 break不急,我们先尝试使用上面的正则去匹配URL测试最后会得到什么

12/^.+ho\/(.*)$/.exec(":8089/ho/asyncreq/log?method=getLog&likeNum=&type1423=") // 测试得到了一个数组 [":8089/ho/asyncreq/log?method=getLog&likeNum=&type1423=", "api/v4/answers//concerned_upvoters?limit=5&offset=0"]

看到 rewrite 还有一个 $1,就是取数组的第二个的意思那么得到可以得到/asyncreq/log?method=getLog&likeNum=&type1423=就是这个没错了,我们就要这个

proxy_pass

proxy_pass 的作用是设置被代理的服务器的协议和地址

协议可以是 http 或者 https

地址可以是 域名 或者 IP+端口

既然拿到了 正确的api路径,那么我们现在要做的就是确定要真正发送请求的服务器的域名比如是 所以设置 proxy_pass 为 

那么最后我们发出去的请求就是?method=getLog&likeNum=&type1423=

重启nginx

我们已经修改了配置文件了,现在要做的就是重启nginx运行命令 nginx -s reload到这一步,nginx 相关的我们都做完啦,下面就写一个页面测试一下接口反向代理是否成功

写测试页面

新建一个 nginx.html 文件放在 nginx解压目录下的 html 中

1234567891011121314151617<!DOCTYPE html><html><head>    <title>nginx 反向代理解决跨域</title></head><body>    <div></div>    <script src=""></script>    <script type="text/javascript">        $(function() {            $.get(":8089/ho/api/v4/answers//concerned_upvoters?limit=5&offset=0", function(result) {                console.log(result,33)            });        })    </script></body></html>

然后打开这个页面,打开链接 :8089/nginx.html

最后我们可以在控制台看到请求返回的信息

我还能说什么?不就是成功了喽

结尾

在做项目的时候,调用后端项目的时候总是会涉及到跨域。而JSONP需要后端配合根本就是很少用,要不然也只能去求后端爸爸设置一下响应头部现在,我们不用求别人了!!靠自己,就能解决跨域问题!!!

PS:感觉文章排版还是乱乱的