如何搞定前端资源服务nginx 跨域配置问题之nginx篇

Nginx能为前端开发带来什么? - 腾讯Web前端 IMWeb 团队社区 | blog | 团队博客
已有账号,立即登录
通过以下账号登录:
imweb是真人前端社区,填写公司信息能帮助你更好的提升业内影响力。
公司邮箱仅作一次性的验证使用,您不必担心信息泄露与垃圾邮件。
如今,他们已入驻imweb:
填写公司信息
自由职业者,学生,或待业中?
返回上一步
(1421浏览)
(4006浏览)
(1546浏览)
(1699浏览)
本文作者:imweb 黎腾
原文出处:
未经同意,禁止转载
Nginx那么好,我想去看看。接连逛了两个书城后,我发现并没有Nginx相关的书籍。这就很奇怪!
Nginx,一名网红(网络服务器红人…),就算没有自传和回忆录,争着介绍它的花边新闻也该有吧。
后来找到仅有的一两本书籍,也直接深入到“源码剖析”的阶段。写得并不十分满意,况且我还不需要这些。后来发现了原因,大概是因为“使用太简单了,都不值得出书”。是的,Nginx把纷繁复杂的功能,浓缩成一份简单的配置,极易上手。当它呈现到你面前时,感觉独具匠心。
Nginx与NodeJs
(这里的标题有点歧义。此处的NodeJs,皆引申为NodeJs所搭建的服务器。)
有人说,作为一名前端,我的真爱是NodeJs。同时也认同,抛去性能之类的比较,单纯从实现的角度,NodeJs编写的服务器也能实现Nginx的各种功能。
这些我都赞成,但使用Nginx并不意味着抛弃NodeJs。事实上,它们并不冲突,还可以在一起愉快的玩耍。
在业内,这样的模型已很常见:资源转发,反向代理,静态资源处理,负载均衡,这些事情扔给Nginx来处理,只是几行配置的事情;同时在上游,让NodeJs去处理它最擅长的I/O等事情。
合理分配各自擅长的事情,这样的思路,同样可以运用于前端开发中。
以前用NodeJs几百行实现的服务器功能,在npm与github的海洋里花尽心思去寻找的模块,也许在Nginx里是一条成熟的配置。它能帮其分担很多事情,节约了成本。
场景一:环境切换
前端开发中,经常面临多个部署环境切换的问题。我们通常用配hosts的方式去实现。更优化些,我们将机器的服务绑定了不同的域名:比如正式环境是,测试环境是test.。
然而在拓展性和易用性方面,还不足够好。而Nginx作为反向代理,就很容易处理资源转发的问题。
思路很简单:
读取请求里的cookie,如果键名host_id有值,则代理到这个IP地址;
如果没有,则代理到默认的正式环境(此处举例为1.1.1.1);
set $env_id "1.1.1.1";
if ( $http_cookie~* "host_id=(\S+)(;.*|$)") {
set $env_id $1;
location / {
proxy_set_header Host $host;
proxy_pass
http://$env_id:80;
那接下来的事情,就是怎样用最简便的方式,把IP种在cookie里?我们应用了nginx-http-footer-filter模块,html文件经过代理时,都注入了一小段js代码。
这段代码,会帮我们展示小菜单,点击某个环境时,则将IP种到cookie里,同时刷新页面,让Nginx完成环境切换。
切换环境,如今只需点击一次。
场景二:SourceMap
在线上环境调试Js代码是件麻烦的事情,因为目前合格的前端部署,代码都应经过压缩。性能问题是优化了,debug可不怎么方便。
而SourceMap正好可以解决此问题。
在最新的各版本浏览器里,如果满足:
压缩后的js文件后面有//# sourceMappingURL=xxx.map格式的注释
浏览器能正常访问到sourceMappingURL
那么,就能把压缩过的代码还原。
要实现这样的功能,就必须:
现网环境不带以上形式的注释,同时访问不到sourceMap(安全性考虑)
测试环境带注释,能访问sourceMap
这样的模型,用反向代理+内容纂改的思路再合适不过。每次构建编译时,我们会把sourceMap文件存放到一台机器(举例为1.1.1.1),命名为js文件名后加.map后缀。随后,使用Nginx,通过这几行配置就能把此功能实现:
location ~ \.js$ {
footer "\n//# sourceMappingURL=$request_uri.map";
footer_types "*";
只要经过代理,在chrome里,我们能看到每份被压缩过的js文件,都有一个对应的源码文件。你可以直接使用它来做打断点之类的操作,大大的提升了调试质量。
场景三:内容纂改
其实在以上两个场景里,都涉及了“内容纂改”。无论是说“纂改”还是“劫持”,大家的印象都不是什么好事情,但另一方面,他们又可以让事情有趣起来。
统一介绍下,Nginx涉及纂改的模块有:
:往文件的底部添加文字,可包含Nginx的内置变量;
:从一个url去读取内容,将之添加到文件的头部或顶部;
:替换字符
除去上面两种场景,合理运用这些模块对应的配置,可以做出许多小工具,这是很有想象力的事情。单单针对移动web前端开发,就可以实现:
将脚本插入到html里,让移动web调试更加便捷。
移动web经常用到localStorage优化首屏,但debug时又会受到干扰,通过一个按钮很方便的清除本地缓存。
手机APP内嵌页面,很难将其网址分享给另一个人。通过一个按钮就能生成url对应的二维码等
场景四:本地映射
在Windows下的前端抓包调试,Fiddler+Willow的能力毋庸置疑。而脱离了.NET体系的Linux和Mac,即使有一些代替工具,但某些方面还是略显不足。
比如:线上接口映射到本地文件。想到Fiddler的本质也是一个代理,而开启一个有这样能力的Nginx服务,并不是太难的事情。
而且,我们可以做得更灵活,比如:
同时支持慢速调试
同时支持目录层级映射
同时支持正则匹配
JSON返回的数据有可能是变化的(比如分页时候),同时支持动态数据
这些场景,只运用到Nginx里的“”。从参考的文档可以大致看到,rewrite规则非常灵活,能完成各种场景的转发。
最简单的模型中,我们把所有带cgi-bin路径的请求,rewite到本地的一个服务,同时带上请求的所有参数,仅需这三行配置即可:
location ~ /cgi-bin/* {
rewrite ^(.*)$ http://127.0.0.1:8080/cgi-bin/ last;
后续的事情,可以在本地创建一个cgi-bin文件夹,在里面放置需要映射的文本,并开启服务到8080端口即可。
场景五:移动侧调试
Fiddler 有一个勾选项 Allow remote computers to connect,并可以指定 listen port 可以使得手机/其它终端通过将本机设为代理而访问本机环境,与 hosts 配合会很实用。
这个功能,用Nginx也很容易做到。通过 default_server 作为代理,手机终端通过设置网络代理为本机IP和相应的 listen port,从而可以访问本机的 Web 服务。
其中也是用到了模块的配置:
80 default_
resolver 8.8.8.8;
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-Ip $remote_
proxy_set_header X-Forwarded-For $remote_
proxy_pass http://$host;
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-Ip $remote_
proxy_set_header X-Forwarded-For $remote_
proxy_pass http://127.0.0.1:9091/;
除去特定场景,Nginx的一些配置也跟前端息息相关。以下简单罗列,作为边角材料。
1.资源合并,处理CDN combo。例如通过这样的方式/??style1.css,style2.css,foo/style3.css访问合并后的资源。
2.图片处理。提供图片缩放,jpg压缩,旋转等特性。
3.适配PC与移动web总体可运用,去实现路径转发。判断平台类型的Nginx配置,在开源项目中可以找到。
学习Nginx,我本身只是出于开开眼界的目的。而的确发现了一些很有启发性的特质。于前端开发,无论线上线下,熟练掌握基本配置,可以做出许多提高效率的工具。但既然是工具,熟手就好。
比如Fiddler直观,但Nginx更底层,更灵活,应当按照实际选择即可。
话说回来,后来心情有些惆怅。想起之前,我用NodeJs写过一个八百行的本地调试服务,如今更习惯用Nginx的几行配置。不过我又想,既然我已经花了时间去写,为什么还要花时间去用?!
心情又好起来了。(等等有什么不对,管它呢…)
END.15.11.03 Litten.浏览器跨域访问解决方案
5099次浏览
跨域的概念
跨域大家都知道,不同地址,不同端口,不同级别,不同协议都会构成跨域。例如:和都会构成跨域。总结起来只要协议、域名、端口有任何一个不同,都被当作是不同的域。下面举例,每两个一组。
是否允许通信
同一域名下
/script/b.js 同一域名下不同文件夹 允许
:8000/a.js
同一域名,不同端口
/b.js 同一域名,不同协议 不允许
http://60.32.92.74/b.js 域名和域名对应ip 不允许
/b.js 主域相同,子域不同 不允许
/b.js 同一域名,不同二级域名(同上) 不允许(cookie这种情况下也不允许访问)
/b.js 不同域名 不允许
解决跨域的方案
上一篇文章,我写了,是一种跨域的解决方案。今天再介绍几个。
CORS跨域资源共享
众所周知,我们之前跨域很多时候用的是jsonp的方式,jsonp的方式我后面介绍。下面说说CORS跨域和jsonp跨域的优势:
CORS与JSONP相比,无疑更为先进、方便和可靠。
1、 JSONP只能实现GET请求,而CORS支持所有类型的HTTP请求。
2、 使用CORS,开发者可以使用普通的XMLHttpRequest发起请求和获得数据,比起JSONP有更好的错误处理。
3、 JSONP主要被老的浏览器支持,它们往往不支持CORS,而绝大多数现代浏览器都已经支持了CORS。[低版本IE7以下不支持,要支持IE7还是要用jsonp方式]
CORS的使用
CORS要前后端同时做配置。
1、首先我们来看前端。
纯js的ajax请求。
&script type=&text/javascript&&
var xhr = new XMLHttpRequest(); //ie6以下用new ActiveXObject(&Microsoft.XMLHTTP&);可以做能力判断。
xhr.open(&?GET&, &/haorooms&,true);
xhr.send();
以上的haorooms是相对路径,如果我们要使用CORS,相关Ajax代码可能如下所示:
&script type=&text/javascript&&
var xhr = new XMLHttpRequest();//ie6以下用new ActiveXObject(&Microsoft.XMLHTTP&);可以做能力判断。
xhr.open(&?GET&, &/CORS&,true);
xhr.send();
当然,你也可以用jquery的ajax进行。
2、后端或者服务器端的配置
下面我们主要介绍Apache和PHP里的设置方法。
Apache:Apache需要使用mod_headers模块来激活HTTP头的设置,它默认是激活的。你只需要在Apache配置文件的
& Directory &, & Location&, & Files &或& VirtualHost&的配置里加入以下内容即可:
Header set Access-Control-Allow-Origin *
PHP:只需要使用如下的代码设置即可。
header(&Access-Control-Allow-Origin:*&);
以上的配置的含义是允许任何域发起的请求都可以获取当前服务器的数据。当然,这样有很大的危险性,恶意站点可能通过XSS攻击我们的服务器。所以我们应该尽量有针对性的对限制安全的来源,例如下面的设置使得只有这个域才能跨域访问服务器的API。
Access-Control-Allow-Origin:
通过jsonp跨域
jsonp跨域也需要前后端配合使用。一般后端设置callback ,前端给后台接口中传一个callback 就可以。
例如前端代码:
&script type=&text/javascript&&
function dosomething(jsondata){
//处理获得的json数据
&script src=&/data.php?callback=dosomething&&&/script&
后台代码:
$callback = $_GET['callback'];//得到回调函数名
$data = array('a','b','c');//要返回的数据
echo $callback.'('.json_encode($data).')';//输出
假如你用ajax方式进行jsonp跨域,我之前的一篇文章中提及过:
//简写形式,效果相同
$.getJSON(&url跨域地址&,
{参数,要把callback作为参数传到后端},
function(data){
//结构处理
},&jsonp&);
type : &get&,
url : &跨域地址&,
dataType : &jsonp&,//数据类型为jsonp
jsonp: &callback&,//服务端用于接收callback调用的function名的参数【后台接受什么参数,我们就传什么参数】我们上面设置是callback
success : function(data){
//结果处理
error:function(data){
console.log(data);
通过修改document.domain来跨子域
我们只需要在跨域的两个页面中设置document.domain就可以了。修改document.domain的方法只适用于不同子域的框架间的交互。
例如:1.在页面 http:// /a.html
中设置document.domain
&iframe id = &iframe& src=&/b.html& onload = &test()&&&/iframe&
&script type=&text/javascript&&
document.domain = &#';//设置成主域
function test(){
alert(document.getElementById('?iframe').contentWindow);//contentWindow 可取得子窗口的 window 对象
2、在页面http:// /b.html
中设置document.domain
&script type=&text/javascript&&
document.domain = &#';//在iframe载入这个页面也设置document.domain,使之与主页面的document.domain相同
使用window.name来进行跨域
window对象有个name属性,该属性有个特征:即在一个窗口(window)的生命周期内,窗口载入的所有的页面都是共享一个window.name的,每个页面对window.name都有读写的权限,window.name是持久存在一个窗口载入过的所有页面中的。
假如有三个页面。
</app.html:应用页面。
a.com/proxy.html:代理文件,一般是一个没有任何内容的html文件,需要和应用页面在同一域下。
b.com/data.html:应用页面需要获取数据的页面,可称为数据页面。
1、在应用页面(a.com/app.html)中创建一个iframe,把其src指向数据页面(b.com/data.html)。
数据页面会把数据附加到这个iframe的window.name上,data.html代码如下:
&script type=&text/javascript&&
window.name = &#39;I was there!&#39;;
// 这里是要传输的数据,大小一般为2M,IE和firefox下可以大至32M左右
// 数据格式可以自定义,如json、字符串
2、在应用页面(a.com/app.html)中监听iframe的onload事件,在此事件中设置这个iframe的src指向本地域的代理文件(代理文件和应用页面在同一域下,所以可以相互通信)。
app.html部分代码如下:
&script type=&text/javascript&&
var state = 0,
iframe = document.createElement(&#39;iframe&#39;),
loadfn = function() {
if (state === 1) {
var data = iframe.contentWindow.
// 读取数据
alert(data);
//弹出&#39;I was there!&#39;
} else if (state === 0) {
state = 1;
iframe.contentWindow.location = &http://a.com/proxy.html&;
// 设置的代理文件
iframe.src = &#39;http://b.com/data.html&#39;;
if (iframe.attachEvent) {
iframe.attachEvent(&#39;onload&#39;, loadfn);
iframe.onload
document.body.appendChild(iframe);
3、获取数据以后销毁这个iframe,释放内存;这也保证了安全(不被其他域frame js访问)。
&script type=&text/javascript&&
iframe.contentWindow.document.write(&#39;&#39;);
iframe.contentWindow.close();
document.body.removeChild(iframe);
使用HTML5的window.postMessage方法跨域
具体请看上一篇博客:
相关文章:
关键词搜索查看: 8741|回复: 16
注册时间最后登录在线时间23 小时阅读权限70积分2274帖子主题精华0UID8283
金牌会员, 积分 2274, 距离下一级还需 7726 积分
28注册时间最后登录在线时间23 小时阅读权限70积分2274帖子主题精华0UID8283
本帖最后由 baia 于
14:33 编辑
因为我后端用的域名和服务器交叉,
域名有5个绑定到10多台服务器上了,出问题的时候很难排查
不知道是哪个域名访问的哪个后端IP,请高手提示一下。十分感谢!
目前是这样配置的:
五个域名:
10台后端服务器:
每台服务器绑定以上5个域名
1个前端服务器:
将五个域名的DNS全部指向到该代理服务器
用户访问这5个域名都是先访问这台代理服务器,代理服务器再向后端请求
总体感觉比较复杂
补充内容 ( 19:17):
谢谢朋友们,找到一个办法:用了yaoweibing开发的nginx check 模块
注册时间最后登录在线时间19 小时阅读权限70积分4837帖子主题精华0UID37155
金牌会员, 积分 4837, 距离下一级还需 5163 积分
注册时间最后登录在线时间19 小时阅读权限70积分4837帖子主题精华0UID37155
不知LZ这是否试过日志分析Nginx日志,可在日志格式定义中加入&$upstream_addr“,&$upstream_status&。进行日志分析。这里提供LZ尝试一下。
注册时间最后登录在线时间3 小时阅读权限30积分586帖子主题精华0UID875
中级会员, 积分 586, 距离下一级还需 214 积分
注册时间最后登录在线时间3 小时阅读权限30积分586帖子主题精华0UID875
有2个方法:
1. 在编译安装Nginx之前修改Nginx的版本信息,你可以每台服务器的Nginx版本信息可以编译不同,比如Nginx-1&&Nginx-2;然后可以通过firebug等浏览器插件查看;
2. 通过Nginx的add_header指令可以进行查看。
具体可以看看这个&&
首先,修改nginx的配置
在server里 增加一行; 如下
add_header Vary ff-bb-1;
reload Nginx配置
然后安装Firefox的插件firebug ,安装好之后,按F12 可以看到firebug的控制面板,点击网络标签,并启用面板
注册时间最后登录在线时间485 小时阅读权限90积分169865帖子主题精华0UID15647
注册时间最后登录在线时间485 小时阅读权限90积分169865帖子主题精华0UID15647
路过了解一下
注册时间最后登录在线时间14 小时阅读权限70积分3589帖子主题精华0UID20912
金牌会员, 积分 3589, 距离下一级还需 6411 积分
注册时间最后登录在线时间14 小时阅读权限70积分3589帖子主题精华0UID20912
killed000 发表于
有2个方法:
1. 在编译安装Nginx之前修改Nginx的版本信息,你可以每台服务器的Nginx版本信息可以编译不同, ...
楼上这种方法很好。我也给出一种小办法。在 每个网站下建立一个test.html& &比方说这个文件里写的是ip。不同的主机这个文件不同,应该可以区别出来,当你想知道访问的是哪个机器的时候放问 /test.html 就可以了
注册时间最后登录在线时间59 小时阅读权限100积分3279帖子主题精华0UID2266
注册时间最后登录在线时间59 小时阅读权限100积分3279帖子主题精华0UID2266
抱歉。完全没有看懂。卤煮的nginx反向代理服务器的upstreams段是怎么写的?上面没有用ip方式?
注册时间最后登录在线时间260 小时阅读权限90积分54287帖子主题精华0UID17344
注册时间最后登录在线时间260 小时阅读权限90积分54287帖子主题精华0UID17344
淘宝的开源插件 Nginx-Http-Footer-Filter 也可以考虑试试
注册时间最后登录在线时间156 小时阅读权限90积分16029帖子主题精华0UID9647
注册时间最后登录在线时间156 小时阅读权限90积分16029帖子主题精华0UID9647
daocaoren0311 发表于
楼上这种方法很好。我也给出一种小办法。在 每个网站下建立一个test.html& &比方说这个文件里写的是ip。 ...
恩 还有7楼提到的扩展 也不错 无痛 直白 在用
注册时间最后登录在线时间2 小时阅读权限0积分689帖子主题精华0UID40310
注册时间最后登录在线时间2 小时阅读权限0积分689帖子主题精华0UID40310
提示: 作者被禁止或删除 内容自动屏蔽
注册时间最后登录在线时间31 小时阅读权限70积分6520帖子主题精华0UID14901
金牌会员, 积分 6520, 距离下一级还需 3480 积分
注册时间最后登录在线时间31 小时阅读权限70积分6520帖子主题精华0UID14901
安装一个叫 nginx_upstream_check_module 的第三方模块,检查后端服务器的情况,如果后端服务器故障自动摘除, 加入& &
location /check_status {
& & check_
& & access_
} 可查看哪台机器被摘除了。
注册时间最后登录在线时间23 小时阅读权限70积分2274帖子主题精华0UID8283
金牌会员, 积分 2274, 距离下一级还需 7726 积分
注册时间最后登录在线时间23 小时阅读权限70积分2274帖子主题精华0UID8283
碟舞飞扬 发表于
安装一个叫 nginx_upstream_check_module 的第三方模块,检查后端服务器的情况,如果后端服务器故障自动摘 ...
谢谢,装上了
注册时间最后登录在线时间2 小时阅读权限30积分360帖子主题精华0UID40702
中级会员, 积分 360, 距离下一级还需 440 积分
注册时间最后登录在线时间2 小时阅读权限30积分360帖子主题精华0UID40702
Keycer是一家位于荷兰的基础网络服务提供商,全球IP单一架构,在客户单台服务器,提供任意国家的IP
全能独立IP空间,支持IP访问网站,独立IP更利于SEO,让您选择更专业,海外免备案空间,海外服务器,稳定高速。
全球最低价 限量50台供应
每人限购3台
o& & & & 6核心CPU
o& & & & 12GB 内存
o& & & & 2TB硬盘
o& & & & 1TB流量
o& & & & 256个C段不连续IP
o& & & & 大机房质量保障/全球IP
更多请点击:
详情咨询QQ:
注册时间最后登录在线时间23 小时阅读权限70积分2274帖子主题精华0UID8283
金牌会员, 积分 2274, 距离下一级还需 7726 积分
注册时间最后登录在线时间23 小时阅读权限70积分2274帖子主题精华0UID8283
ヤ木兮°ゞヤゝ 发表于
不知LZ这是否试过日志分析Nginx日志,可在日志格式定义中加入&$upstream_addr“,&$upstream_status&。进行 ...
我们的数据量太大,并发1万多连接,开日志一会就好几百M了
注册时间最后登录在线时间23 小时阅读权限70积分2274帖子主题精华0UID8283
金牌会员, 积分 2274, 距离下一级还需 7726 积分
注册时间最后登录在线时间23 小时阅读权限70积分2274帖子主题精华0UID8283
killed000 发表于
有2个方法:
1. 在编译安装Nginx之前修改Nginx的版本信息,你可以每台服务器的Nginx版本信息可以编译不同, ...
我们后端是IIS,前端是nginx……
注册时间最后登录在线时间23 小时阅读权限70积分2274帖子主题精华0UID8283
金牌会员, 积分 2274, 距离下一级还需 7726 积分
注册时间最后登录在线时间23 小时阅读权限70积分2274帖子主题精华0UID8283
lyf362345 发表于
恩 还有7楼提到的扩展 也不错 无痛 直白 在用
这种效果,也不是很合适,比如像这种情况:后端服务器IIS,需要接受到用户传的文件之后,做出信息反馈,它平时页面都正常,访问页面肯定也正常,假如现在这台机器的磁盘满了,或者连接不上数据库,这两个问题都需要用户传完文件之后再做反馈的。所以的话,这种情况也不能用
Powered by18572人阅读
Javascript(59)
1.同源策略如下:
是否允许通信
同一域名下
/script/b.js
同一域名下不同文件夹
:8000/a.js
同一域名,不同端口
同一域名,不同协议
http://70.32.92.74/b.js
域名和域名对应ip
主域相同,子域不同
http://a.com/b.js
同一域名,不同二级域名(同上)
不允许(cookie这种情况下也不允许访问)
特别注意两点:第一,如果是协议和端口造成的跨域问题“前台”是无能为力的,第二:在跨域问题上,域仅仅是通过“URL的首部”来识别而不会去尝试判断相同的ip地址对应着两个域或两个域是否在同一个ip上。“URL的首部”指window.location.protocol &#43;window.location.host,也可以理解为“Domains, protocols and ports must match”。
2. 前端解决跨域问题
1& document.domain &#43; iframe & & &(只有在主域相同的时候才能使用该方法)
1) 在/a.html中:
document.domain = 'a.com';
var ifr = document.createElement('iframe');
ifr.src = 'http://www./b.html';
ifr.display =
document.body.appendChild(ifr);
ifr.onload = function(){
var doc = ifr.contentDocument || ifr.contentWindow.
//在这里操作doc,也就是b.html
ifr.onload = null;
2) 在www./b.html中:
document.domain = 'a.com';
2& 动态创建script
这个没什么好说的,因为script标签不受同源策略的限制。
function loadScript(url, func) {
var head = document.head || document.getElementByTagName('head')[0];
var script = document.createElement('script');
script.src =
script.onload = script.onreadystatechange = function(){
if(!this.readyState || this.readyState=='loaded' || this.readyState=='complete'){
script.onload = script.onreadystatechange = null;
head.insertBefore(script, 0);
window.baidu = {
sug: function(data){
console.log(data);
loadScript('/su?wd=w',function(){console.log('loaded')});
//我们请求的内容在哪里?
//我们可以在chorme调试面板的source中看到script引入的内容
3& location.hash &#43; iframe
原理是利用location.hash来进行传&#20540;。
假设域名a.com下的文件cs1.html要和域名下的cs2.html传递信息。
1) cs1.html首先创建自动创建一个隐藏的iframe,iframe的src指向域名下的cs2.html页面
2) cs2.html响应请求后再将通过修改cs1.html的hash&#20540;来传递数据
3) 同时在cs1.html上加一个定时器,隔一段时间来判断location.hash的&#20540;有没有变化,一旦有变化则获取获取hash&#20540;
注:由于两个页面不在同一个域下IE、Chrome不允许修改parent.location.hash的&#20540;,所以要借助于a.com域名下的一个代理iframe
代码如下:
先是a.com下的文件cs1.html文件:
function startRequest(){
var ifr = document.createElement('iframe');
ifr.style.display = 'none';
ifr.src = '/lab/cscript/cs2.html#paramdo';
document.body.appendChild(ifr);
function checkHash() {
var data = location.hash ? location.hash.substring(1) : '';
if (console.log) {
console.log('Now the data is '&#43;data);
} catch(e) {};
setInterval(checkHash, 2000);
域名下的cs2.html:
//模拟一个简单的参数处理操作
switch(location.hash){
case '#paramdo':
callBack();
case '#paramset':
//do something……
function callBack(){
parent.location.hash = 'somedata';
} catch (e) {
// ie、chrome的安全机制无法修改parent.location.hash,
// 所以要利用一个中间的cnblogs域下的代理iframe
var ifrproxy = document.createElement('iframe');
ifrproxy.style.display = 'none';
ifrproxy.src = 'http://a.com/test/cscript/cs3.html#somedata';
// 注意该文件在&&域下
document.body.appendChild(ifrproxy);
a.com下的域名cs3.html
//因为parent.parent和自身属于同一个域,所以可以改变其location.hash的&#20540;
parent.parent.location.hash = self.location.hash.substring(1);
4& window.name &#43; iframe
window.name 的美妙之处:name &#20540;在不同的页面(甚至不同域名)加载后依旧存在,并且可以支持非常长的 name &#20540;(2MB)。
1) 创建a.com/cs1.html
2) 创建a.com/proxy.html,并加入如下代码
function proxy(url, func){
var isFirst = true,
ifr = document.createElement('iframe'),
loadFunc = function(){
if(isFirst){
ifr.contentWindow.location = 'http://a.com/cs1.html';
isFirst = false;
func(ifr.contentWindow.name);
ifr.contentWindow.close();
document.body.removeChild(ifr);
ifr.src = '';
ifr = null;
ifr.style.display = 'none';
if(ifr.attachEvent) ifr.attachEvent('onload', loadFunc);
else ifr.onload = loadF
document.body.appendChild(iframe);
proxy('/', function(data){
console.log(data);
3 在b.com/cs1.html中包含:
window.name = '要传送的内容';
5& postMessage(HTML5中的XMLHttpRequest Level 2中的API)
1) a.com/index.html中的代码:
&iframe id=&ifr& src=&/index.html&&&/iframe&
&script type=&text/javascript&&
window.onload = function() {
var ifr = document.getElementById('ifr');
var targetOrigin = 'http://b.com';
// 若写成'http://b.com/c/proxy.html'效果一样
// 若写成'http://c.com'就不会执行postMessage了
ifr.contentWindow.postMessage('I was there!', targetOrigin);
2) b.com/index.html中的代码:
&script type=&text/javascript&&
window.addEventListener('message', function(event){
// 通过origin属性判断消息来源地址
if (event.origin == 'http://a.com') {
alert(event.data);
// 弹出&I was there!&
alert(event.source);
// 对a.com、index.html中window对象的引用
// 但由于同源策略,这里event.source不可以访问window对象
}, false);
CORS背后的思想,就是使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功,还是应该失败。
IE中对CORS的实现是xdr
var xdr = new XDomainRequest();
xdr.onload = function(){
console.log(xdr.responseText);
xdr.open('get', '');
xdr.send(null);
其它浏览器中的实现就在xhr中
new XMLHttpRequest();
xhr.onreadystatechange = function () {
if(xhr.readyState == 4){
if(xhr.status &= 200 && xhr.status & 304 || xhr.status == 304){
console.log(xhr.responseText);
xhr.open('get', '');
xhr.send(null);
实现跨浏览器的CORS
function createCORS(method, url){
var xhr = new XMLHttpRequest();
if('withCredentials' in xhr){
xhr.open(method, url, true);
}else if(typeof XDomainRequest != 'undefined'){
var xhr = new XDomainRequest();
xhr.open(method, url);
xhr = null;
var request = createCORS('get', '');
if(request){
request.onload = function(){
request.send();
JSONP包含两部分:回调函数和数据。
回调函数是当响应到来时要放在当前页面被调用的函数。
数据就是传入回调函数中的json数据,也就是回调函数的参数了。
function handleResponse(response){
console.log('The responsed data is: '&#43;response.data);
var script = document.createElement('script');
script.src = '/json/?callback=handleResponse';
document.body.insertBefore(script, document.body.firstChild);
/*handleResonse({&data&: &zhe&})*/
//原理如下:
//当我们通过script标签请求时
//后台就会根据相应的参数(json,handleResponse)
//来生成相应的json数据(handleResponse({&data&: &zhe&}))
//最后这个返回的json数据(代码)就会被放在当前js文件中被执行
//至此跨域通信完成
&jsonp虽然很简单,但是有如下缺点:
1)安全问题(请求代码中可能存在安全隐患)
2)要确定jsonp请求是否失败并不容易
8& web sockets
web sockets是一种浏览器的API,它的目标是在一个单独的持久连接上提供全双工、双向通信。(同源策略对web sockets不适用)
web sockets原理:在JS创建了web socket之后,会有一个HTTP请求发送到浏览器以发起连接。取得服务器响应后,建立的连接会使用HTTP升级从HTTP协议交换为web sockt协议。
只有在支持web socket协议的服务器上才能正常工作。
var socket = new WebSockt('ws://');//http-& https-&wss
socket.send('hello WebSockt');
socket.onmessage = function(event){
var data = event.
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:1012828次
积分:12812
积分:12812
排名:第647名
原创:277篇
转载:346篇
评论:118条
(1)(1)(7)(11)(8)(7)(1)(4)(3)(6)(16)(13)(3)(12)(13)(52)(12)(20)(6)(18)(45)(13)(28)(4)(15)(7)(42)(26)(13)(24)(36)(22)(10)(9)(5)(17)(7)(11)(26)(10)(13)(15)(10)

我要回帖

更多关于 nginx 跨域 的文章

 

随机推荐