用nginx的反向代理机制解决前端跨域问题在nginx上部署web静态页面javascript
跨域是指a页面想获取b页面资源,若是a、b页面的协议、域名、端口、子域名不一样,或是a页面为ip地址,b页面为域名地址,所进行的访问行动都是跨域的,而浏览器为了安全问题通常都限制了跨域访问,也就是不容许跨域请求资源。html
跨域状况以下:前端
url | 说明 | 是否跨域 |
http://www.cnblogs.com/a.js http://www.a.com/b.js |
不一样域名 | 是 |
http://www.a.com/lab/a.js http://www.a.com/script/b.js |
同一域名下不一样文件夹 | 否 |
http://www.a.com:8000/a.js http://www.a.com/b.js |
同一域名,不一样端口 | 是 |
http://www.a.com/a.js https://www.a.com/b.js |
同一域名,不一样协议 | 是 |
http://www.a.com/a.js http://70.32.92.74/b.js |
域名和域名对应ip | 是 |
http://www.a.com/a.js http://script.a.com/b.js |
主域相同,子域不一样 | 是(cookie不可访问) |
http://www.a.com/a.js http://a.com/b.js |
同一域名,不一样二级域名(同上) | 是 |
目前来说没有不依靠服务器端来跨域请求资源的技术html5
1.jsonp 须要目标服务器配合一个callback函数。java
2.window.name+iframe 须要目标服务器响应window.name。nginx
3.window.location.hash+iframe 一样须要目标服务器做处理。git
4.html5的 postMessage+ifrme 这个也是须要目标服务器或者说是目标页面写一个postMessage,主要侧重于前端通信。github
5.CORS 须要服务器设置header :Access-Control-Allow-Origin。
web
6.nginx反向代理 这个方法通常不多有人说起,可是他能够不用目标服务器配合,不过须要你搭建一个中转nginx服务器,用于转发请求。ajax
上面已经说到,禁止跨域问题实际上是浏览器的一种安全行为,而如今的大多数解决方案都是用标签能够跨域访问的这个漏洞或者是技巧去完成,但都少不了目标服务器作相应的改变,而我最近遇到了一个需求是,目标服务器不能给予我一个header,更不能够改变代码返回个script,因此前5种方案都被我否决掉。最后由于个人网站是我本身的主机,因此我决定搭建一个nginx并把相应代码部署在它的下面,由页面请求本域名的一个地址,转由nginx代理处理后返回结果给页面,并且这一切都是同步的。
关于nginx的一些基本配置和安装请看个人另外一篇博客,下面直接讲解如何配置一个反向代理。
首先找到nginx.conf或者nginx.conf.default 或者是default里面的这部份
其中server表明启动的一个服务,location 是一个定位规则。
1
2
3
4
5
6
7
|
location /{ #全部以/开头的地址,其实是全部请求
root html #去请求../html文件夹里的文件,其中..的路径在nginx里面有定义,安装的时候会有默认路径,详见另外一篇博客
index index.html index.htm #首页响应地址
}
|
从上面能够看出location是nginx用来路由的入口,因此咱们接下来要在location里面完成咱们的反向代理。
假如咱们咱们是www.a.com/html/msg.html 想请求www.b.com/api/?method=1¶=2;
咱们的ajax:
1
2
3
4
5
6
7
|
var
url = 'http://www.b.com/api/msg?method=1¶=2' ;
<br>$.ajax({
type:
"GET"
,
url:url,
success:
function
(res){..},
....
})
|
上面的请求必然会遇到跨域问题,这时咱们须要修改一下咱们的请求url,让请求发在nginx的一个url下。
1
2
3
4
5
6
7
8
9
|
var
url = 'http://www.b.com/api/msg?method=1¶=2' ;
var
proxyurl = 'msg?method=1¶=2' ;
//假如实际地址是 www.c.com/proxy/html/api/msg?method=1¶=2; www.c.com是nginx主机地址
$.ajax({
type:
"GET"
,
url:proxyurl,
success:
function
(res){..},
....
})
|
再在刚才的路径中匹配到这个请求,咱们在location下面再添加一个location。
1
2
3
4
|
location ^~/proxy/html/{
rewrite ^/proxy/html/(.*)$ /$1
break
;
proxy_pass http:
//www.b.com/;
}
|
1.'^~ /proxy/html/ '
就像上面说的同样是一个匹配规则,用于拦截请求,匹配任何以 /proxy/html/开头的地址,匹配符合之后,中止往下搜索正则。
2.rewrite ^/proxy/html/(.*)$ /$1 break;
表明重写拦截进来的请求,而且只能对域名后边的除去传递的参数外的字符串起做用,例如www.c.com/proxy/html/api/msg?method=1¶=2重写。只对/proxy/html/api/msg重写。
rewrite后面的参数是一个简单的正则 ^/proxy/html/(.*)$ ,$1表明正则中的第一个(),$2表明第二个()的值,以此类推。
break表明匹配一个以后中止匹配。
3.proxy_pass
既是把请求代理到其余主机,其中 http://www.b.com/ 写法和 http://www.b.com写法的区别以下:
不带/
1
2
3
4
|
location /html/
{
proxy_pass http:
//b.com:8300;
}
|
带/
1
2
3
4
|
location /html/
{
proxy_pass http:
//b.com:8300/;
}
|
上面两种配置,区别只在于proxy_pass转发的路径后是否带 “/”。
针对状况1,若是访问url = http://server/html/test.jsp,则被nginx代理后,请求路径会便问http://proxy_pass/html/test.jsp,将test/ 做为根路径,请求test/路径下的资源。
针对状况2,若是访问url = http://server/html/test.jsp,则被nginx代理后,请求路径会变为 http://proxy_pass/test.jsp,直接访问server的根资源。
修改配置后重启nginx代理就成功了。
由于苹果mac os x自带ssh命令,因此咱们只需打开终端输入
1
|
$ ssh user@remote
|
在这以前最好在服务器上上传本身的ssh key,避免每次登录输入密码
稍做等待就链接上服务器了
在终端窗口,按下command+n,打开另外一个终端窗口,并输入
1
|
$ scp ~/local/file user@remote:~/file
|
固然通常咱们上传的是文件夹,因此加上-r
1
|
$ scp -r ~/local/file user@remote:~/file
|
首先检查一下远程服务器是否安装ngnix.
1
|
nginx -V
|
由于博主的服务器已经安装ngnix,因此下面介绍一下mac os x系统安装nginx的方法
首先咱们要用到homebrew,在终端中输入
1
|
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
|
等待安装结束。
再在终端执行,等待安装结束皆可
1
|
brew install nginx
|
brew经常使用命令:
安装软件: brew install *(软件名 eg. brew install nginx)
卸载软件: brew uninstall *
搜索软件: brew search *
显示已经安装软件列表: brew list
更新软件: brew update
更新某具体软件: brew upgrade git
接下来主要是nginx的配置问题,由于nginx的配置项较多,这里就不一一介绍,只把运行一个静态页面须要配置的东西拿出来配置一下
首先能够看一下nginx的默认配置,可经过brew查看
从上图中能够看到,nginx的默认root路径(也就是服务器根目录)是 /usr/local/var/www
默认端口:8080
下面进入nginx的配置文件,咱们也能看到这些信息.
nginx的配置文件是nginx.conf和nginx.conf.default,通常咱们能够从
/usr/local/etc/nginx/ 中找到这两个文件,经过vim打开nginx.conf。
能够在配置中看到这样一段,能够在location的root 中改变文件存放位置
注意:此处有个大坑
默认路径事 /usr/local/var/www,而在配置中又写了root html,因此真是路径是 /usr/local/var/www/html
但咱们cd 进入/usr/local/var/www 并无html文件,因此须要手动建立一个html,并放入工程。
若是发现nginx没有加载到某些文件或是某些页面出现一下403错误,是由于没有权限
输入 chmod 755 问题文件路径就能够解决
修改以后须要中止nginx从新启动:终端输入
nginx -s stop 中止 nginx 重启
在上一步咱们已经知道了 /usr/local/var/www 是系统运行的根目录,那么咱们使用cp命令把咱们的本地文件复制到此处
1
|
cp -r /local/files /des/files
|