`
guoyiqi
  • 浏览: 1050439 次
社区版块
存档分类
最新评论
阅读更多
使用动态的script标签发起Web Services请求
使用动态的script标签和特殊的与JSON相关的JavaScript类来轻松实现无XML的Web services。
从Ajax应用发起到第三方Web服务的请求是一种痛苦,但是新的Web服务减轻了这种痛苦,它提供了返回JSON格式[Hack #7]结果的选择以代替XML格式。事实上,如果你使用动态script标签方法发起Web服务请求,而且Web服务可让你指定一个JavaScript回调函数,你就可以以一种无缝的跨域跨浏览器的方式自由访问Web服务。
下面是你尝试这个动态的script标签请求所需要的:
l   我的JSONscriptRequest类
l   访问返回JSON格式结果并可让你指定回调函数的Web service
为创建JSONscriptRequest类,我提炼了大量已有的信息,然后调整其以满足上面的第二个要求。直到最近,要找到满足那个要求的Web service近乎不可能,除非你自己写一个。幸运的是,Yahoo!已经开始在它的许多Web service上提供其他的选择。特别地,Yahoo!的与很多搜索相关的Web service,以及它的geocoding、map image和traffic等Web service,现在可以返回封装在一个回调函数里的JSON值。
使用Geocoding Web Service
比起使用XMLHttpRequest对象和代理,这个东西算很容易的。JSONscript- Request类做了创建script标签的脏活;这个标签动态地发起实际的Web service请求。举个快速的例子,这里我将使用Yahoo!的Geocoding Web service,将一个邮编94107转化成一个经/纬对:
<html>
<body>
//包含JSONscriptRequest类
<script type="text/javascript" src="jsr_class.js"></script>
<script type="text/javascript">
//定义回调函数
function getGeo(jsonData) {    
    alert('Latitude = ' + jsonData.ResultSet.Result[0].Latitude +
          ' Longitude = ' + jsonData.ResultSet.Result[0].Longitude);
    bObj.removeScriptTag();
}
// web service 调用
var req = 'http://api.local.yahoo.com/MapsService/V1/geocode?appid=YahooDemo
          &output=json&callback=getGeo&location=94107';
//创建一个新的Request对象
bObj = new JSONscriptRequest(req);
//构建动态脚本标签
bObj.buildScriptTag();
//添加脚本标签到页面中
bObj.addScriptTag();
</script>
</body>
</html>
运行这个程序发起一个到Yahoo!的Geocoing Web service的请求,会弹出如图9-5所示的alert框。这个alert框显示了邮编94107的经度和纬度。
图9-5:从Yahoo的Geocoding Web service所得的坐标
Web service请示(上述script里的req变量)指出Web service应该返回JSON编码的数据(output=json),而且数据应该被封装在一个名为getGeo()(callback=getGeo)的回调函数里。你可以剪切并粘贴代码中的URL到你的浏览器中,然后就会看到Web service的输出。输出如下:
getGeo({"ResultSet":{"Result":[{"precision":"zip","Latitude":"37.7668"
,"Longitude":"-122.3959","Address":"","City":"SAN
FRANCISCO","State":"CA","Zip":"94107","Country":"US"}]}});
这是一个有效的JavaScript语句,所以它可以是返回JavaScript的script标签的target(没有回调函数的原始JSON数据,不是有效的JavaScript语句,所以如果它作为script标签的target,那么就会载入失败)。作为比较,看一下这个调用的XML版本的输出(为这本书格式化过):
<?xml version="1.0" encoding="UTF-8"?>
<ResultSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns=
"urn:yahoo:maps" xsi:schemaLocation=
"urn:yahoo:maps http://api.local.yahoo.com/MapsService/V1/GeocodeResponse.
xsd">
<Result precision="zip"><Latitude>37.7668</Latitude>
<Longitude>-122.3959</Longitude><Address></Address>
<City>SAN FRANCISCO</City><State>CA</State><Zip>94107</Zip>
<Country>US</Country></Result>
</ResultSet>
JSONscriptRequest对象的buildScriptTag方法建立了如下的script标签:
<script src="getGeo({"ResultSet":{"Result":[{"precision":"zip",
"Latitude":"37.7668","Longitude":"-122.3959","Address":"","City":"SAN
FRANCISCO","State":"CA","Zip":"94107","Country":"US"}]}});"
 type="text/javascript">
要实际执行Web service请求,script标签就要加到页面里去。addScriptTag方法将script标签附加到已经载入到你的浏览器窗口中的HTML页面里。这个动作引起了getGeo()函数的调用,同时JSON编码的数据被传送给这个函数。下面看看这个标签中最神奇的部分;它是使用JSON编码的数据而不是XML的副作用。当JSON编码的数据以字符串形式作为JavaScript函数的参数时,JavaScript解释器自动将JSON返回值转化成一个JavaScript对象。基本上,解析的步骤是自动完成的,你可以立即引用这些数据:
alert('Latitude = ' + jsonData.ResultSet.Result[0].Latitude +
       ' Longitude = ' + jsonData.ResultSet.Result[0].Longitude);
正反面
HTML script标签是自由访问基于浏览器的应用的最后边界。从你的角度看来,它可能是一个安全漏洞,或者是一个使富客户端更丰富的工具。然而,它最普遍的用处就是网络广告商使用它将多姿多彩的广告拉到你的网页中。
对于普通的Ajax或者Ajaj(Asynchronous JavaScript and JSON)开发者而言,动态script标签方法在某些场景下能使事情变得简单。然而,XMLHttpRequest对象仍然是更可靠的、灵活安全的请求机制(见表9-1)。
表9-1  XMLHttpRequest 与动态script标签对照表
XmlHttpRequest
Dynamic script tag
跨浏览器兼容性
No
Yes
强制的跨域浏览器安全
Yes
No
是否能接收HTTP状态码
Yes
No (fails on any HTTP status other than 200)
是否支持HTTP GET和POST
Yes
No (GET only)
能否发送/接收HTTP头
Yes
No
能否接收XML
Yes
Yes (but only embedded in a JavaScript statement)
能否接收JSON
Yes
Yes (but only embedded in a JavaScript statement)
是否提供同步和异步调用
Yes
No (asynchronous only)
script标签的主要优点在于它并不受Web浏览器跨域安全限制的束缚,以及比
XMLHttpRequest具备更好的浏览器兼容性。进一步来说,如果你的Web service碰巧提供了JSON输出以及一个回调函数,你可以从JavaScript应用中敏捷地访问Web service,而无需解析返回的数据。
在所有的最新浏览器中XMLHttpRequest都有效,但是IE的实现和其他主要浏览器稍微有所不同,从而需要一个兼容性层(例如Sarissa)来使其工作在所有浏览器上。XMLHttpRequest能接收原始的JSON数据,还可以接收XML、普通文本以及HTML。事实上,它能轻松地处理任何非二进制数据。它还能发送和接收独立的HTTP头部,可以执行HTTP GET和POST请求,同时支持同步和异步调用。一言以蔽之,如果你的Web service请求存在问题,譬如无效的XML或者一个服务器错误,XMLHttpRequest为程序员提供了解决这种情况的工具。
相比较而言,script标签提供很少的XMLHttpRequest能力。最值得注意的坏处是它不能优雅地处理错误。如果Web service返回无效的JavaScript语句给script标签,就会产生一个JavaScript错误。如果Web service返回封装在一个回调函数里的无效JSON数据,那么当无效的JSON数据被传给回调函数时会返回一个JavaScript错误。而且,如果你的Web service返回除200(成功)外的HTTP返回码,script标签会默默的失败。
事实上,script标签请求并不是在所有的浏览器上都以同一方式工作。事件处理机制(你如何等待标签来载入)有些不同。技术上来说,动态生成的script标签会异步载入,但是没有可靠的、跨平台的方式来等待script标签载入。微软的IE使用了这里描述的一个方法,而HTML4.0规范建议采用onload事件处理器(尽管它并不是在所有的浏览器上都可用)。
围绕script标签的安全问题也不能被忽视。下载到你的浏览器中的恶意脚本以与你页面中的其他脚本一样的权限级别运行。因此,恶意的脚本能够偷取你的cookies,或者滥用你在服务器端拥有的授权级别。这些恶意脚本能更轻易地使用script标签发送和接收偷来的数据。出于此原因,使用动态script标签方法的应用应该仔细检查。
有了这些缺点,程序员就不会一窝蜂地使用script标签来实现或重新实现Web service请求。然而它对于脚本应用来说仍然是一门有用的技术——可以轻易地从第三方检索非机密数据。
参考资料
配置Apache以处理跨域问题

配置Apache Web服务器使Apache模块能为Ajax域限制提供一个解决方案。

你也许已经知道,到目前为止,XMLHttpRequest不能自动跨域运行。例如,当你下载一个Web页面时,你不能使用Request对象对不同于那个Web页面所在域的其他域发起请求。幸运的是,有一个简单的解决方案能避免此限制——Apache Web服务器的mod_rewrite。“这个模块使用基于规则的重写引擎(基于一个正则表达式的解析器)来重写被请求的URL,”按照Apache的在线文档所说(可见http://httpd.apache.org/docs/1.3/- mod/mod_rewrite.html)。

跨域障碍

在我们阅读这个解决方案的描述之前,让我们来看看一系列示范性的函数,它们完成了XMLHttpRequest的相关工作:

function getXmlHttpObject(){

    if (window.XMLHttpRequest)

        return new XMLHttpRequest();

    else if (window.ActiveXObject)

        return new ActiveXObject("Microsoft.XMLHTTP");

    else {

        alert("XMLHttpRequest not supported!");

        return null;

    }

}

function handleHttpResponse() {

    if (http.readyState == 4) {

        results = http.responseText;

        alert(results);

    }

}

function doSomeStuff() {

    var post_arg1 = document.my_form.post_arg1.value;

    var post_arg2 = document.my_form.post_arg2.value;

    var post_url = 'http://yahoo.com/form_do'

        post_data = 'post_arg1=' + post_arg1 + '&post_arg2=' + post_arg2;

    http.open("POST", post_url);

    http.setRequestHeader('Content-Type',

            'application/x-www-form-urlencoded; charset=UTF-8');

    http.send(post_data);

    http.onreadystatechange = handleHttpResponse;

    return false;

}

var http = getXmlHttpObject();

你所见到的三个函数中的最后一个将被调用来执行HTTP请求。

现在,假设这个脚本在一个URL为http://premshree.org/form的HTML文件中。表单中的某些事件处理器(onBlur、onClick、onSubmit等)触发doSomeStuff(),它接下来发起一个请求到另一个域(yahoo.com)中的form_do。

注意包含表单和JavaScript的HTML文件域和执行动作(http://yahoo.com/ form_do)的文件域之间的不匹配之处。域的不匹配就是问题之源。

跨域的XMLHttpRequest工作

IE和基于Mozilla的浏览器处理跨域请求有所不同。你可以在IE中执行跨域请求;然而,这需要改变浏览器默认的安全设置,或者添加特定的主机到你的“信任主机”列表中。可见http://msdn.microsoft.com/msdnmag/issues/02/06/web/

由于没有一种方法指定哪些页面应该信任其他页面来访问它们的数据,Internet Explorer简单地规定如果两个页面不在同一个域中,它们就不能通信。更确切地说,Zone Manager(可在IE设置的安全项里找到)允许用户设置一个页面可以访问另一个页面,但是如你所知,大多数用户并不做设定,而只是在弹出窗口时才设置。你可以建议用户将页面添加到信任站点区域,或者仅仅在对话框中点Yes……

另一方面,在Mozilla中有签名脚本的概念(可见http://www.mozilla.org/projects/- security/components/signed-scripts.html)。在基于Mozilla的浏览器中,根据包含在跨域请求中的不同域,你应该赋予一个或更多的UniversalBrowser权限。例如,如果你正从本地文件系统访问一个远程主机,也就是说从file://访问http://,你应该开启UniversalBrowserRead权限。

现实的情形是,跨域的XMLHttpRequest请求在你真正在乎的浏览器中并不能

按照你想要的运行方式工作(当然除非你足够疯狂,强迫天真的、信任你的用户处理诸如签名脚本以及信任主机这样的事情)。

存在解决方案吗

是的,感谢一些mod_rewrite的魔法。你所需要的就是RewriteRule指令。

需要对Apache配置文件做出一些配置变化(通常是httpd.conf)。下面就是包含的步骤:

1. 配置Apache,开启proxy:

./configure –enable-proxy

2. 确信开启了RewriteEngine:

RewriteEngine on

3. 添加以下规则:

RewriteRule ^/form_do$ http://yahoo.com/form_do [p]

这里你所见的P标志表示一个pass-through proxy。

提示:可见http://www.google.com/search?q=pass-through+ proxying

现在,在JavaScript代码中不再请求http://yahoo.com/form_do,而是使用URL /form_do。请求代码如下所示:

var post_url = '/form_do';

就这样——你完成了!感谢Gopan以及http://t3.dotgnu.info为本hack提供了大量信息。

——Premshree Pillai

分享到:
评论

相关推荐

    PhD_Thesis_Cristina_Pinneri.pdf

    PhD_Thesis_Cristina_Pinneri

    Git知识学习(尚硅谷)

    Git知识学习(尚硅谷)

    套筒机械加工工艺规程制订设计.rar

    套筒机械加工工艺规程制订设计.rar

    The First Adventures on Differential Geometry 9789811296178.pdf

    The First Adventures on Differential Geometry 9789811296178

    汽车防误踏油门机构的设计.zip

    汽车防误踏油门机构的设计.zip

    汽车离合器设计.zip

    汽车离合器设计.zip

    基于SpringBoot的文学创作社交论坛(源码+数据库+万字文档+ppt)533

    基于SpringBoot的文学创作社交论坛,系统包含两种角色:管理员、用户主要功能如下。 【用户功能】 1. **首页:** 浏览社交论坛的主要信息。 2. **火车信息:** 阅读和浏览用户发布的文学创作。 3. **公告资讯:** 查看社交论坛发布的重要通知和公告。 4. **后台管理:** - **首页:** 进行后台管理相关操作。 - **个人中心:** 管理个人信息,查看火车票订购历史等。 - **车票预订管理:** 预订文学创作,选择特定的创作者或主题。 - **车票退票管理:** 处理用户对已预订文学创作的退票请求。 5. **个人中心:** 管理个人信息。 【管理员功能】 1. **首页:** 查看社交论坛整体概况。 2. **个人中心:** 修改密码、管理个人信息。 3. **用户管理:** 审核和管理注册用户的信息。 4. **火车类型管理:** 管理文学创作的分类信息。 5. **火车信息管理:** 监管和管理社交论坛上的文学创作信息。 6. **车票预订管理:** 查看和管理用户的文学创作预订情况。 7. **车票退票管理:** 处理用户对已预订文学创作的退票请求。 8. **系统管理:** - **公告资讯:** 发布、编辑和删除系统的通知和公告。 - **关于我们:** 编辑和更新社交论坛的介绍。 - **系统简介:** 提供社交论坛的简要介绍。 - **轮播图管理:** 管理社交论坛首页的轮播图。 二、项目技术 编程语言:Java 数据库:MySQL 项目管理工具:Maven 前端技术:Vue 后端技术:SpringBoot 三、运行环境 操作系统:Windows、macOS都可以 JDK版本:JDK1.8以上都可以 开发工具:IDEA、Ecplise、Myecplise都可以 数据库

    数控铣床主轴箱设计.zip

    数控铣床主轴箱设计.zip

    某电镀废水工艺流程及平面布置图.zip

    某电镀废水工艺流程及平面布置图.zip

    joblib-0.9.0b4-py2.7.egg

    该资源为joblib-0.9.0b4-py2.7.egg,欢迎下载使用哦!

    价值60元的带会员和后台版的域名防红1.19最新免授权开心版

    管理会员制度渠道,掌管多种服务,黑白名单管理邮箱配置生成提醒发送对接易支付进行交易,订单列表,带有各种短网址功能提供接口对接,实现短网址+防红两不误,可自定义多中转域名,自动识别安全网址各种防红数据后台可显,自定义跳转网站 用户端android-ios 会员制度享受,自定义跳转网站,在线充值,我的生成,在线生成,为你的网址提供保护短网址列表接口文档数据显示,编辑我的生成 防红效果全网 在短网址与防红的前提下,为你的网站提供SEO服务以及腾讯相关网站检测的优化 贴吧+短视频平台+ios+android+pc皆正常 安装:上传源码,访问安装。提示授权时,随意填写 6位数字即可

    joblib-0.9.0b3.tar.gz

    该资源为joblib-0.9.0b3.tar.gz,欢迎下载使用哦!

    实时操作系统毕业设计项目内含说明书.zip

    实时操作系统毕业设计项目内含说明书.zip

    python相关学习资源,python

    python

    塑料瓶自动封口机设计.rar

    塑料瓶自动封口机设计.rar

    CarPlay 系统功能介绍,比较专业的文档,告诉我们开发Carplay的时候需要遵循的规则

    内容概要:本文介绍了苹果公司在WWDC19上发布的CarPlay系统的最新进展,主要包括四个方面的改进:不规则形状显示屏支持、多屏显示支持、动态屏幕尺寸调整以及“嘿,Siri”语音助手集成。不规则形状显示屏支持允许开发者为CarPlay定义交互区域,确保内容适应各种非矩形屏幕。多屏显示支持使车辆可以在多个屏幕上同时展示CarPlay界面,如中心控制台和仪表盘,提供导航、音乐播放等不同内容,并支持独立的夜间模式。动态屏幕尺寸调整功能让CarPlay界面可以实时调整大小,以适应不同的驾驶环境或用户需求。最后,“嘿,Siri”功能让用户可以通过语音唤醒Siri,即使在播放音乐时也能无缝交互,系统内置了持续的回声消除和降噪处理,确保语音识别的准确性。; 适合人群:汽车制造商、软件开发者以及对车载信息系统感兴趣的科技爱好者。; 使用场景及目标:①汽车制造商可以根据新的CarPlay特性优化车内娱乐和导航系统的用户体验;②开发者可以利用这些新特性创建更加丰富的车载应用程序;③科技爱好者可以了解最新的车载技术发展趋势。; 其他说明:文档详细描述了CarPlay系统的技术细节,包括语音活动检测器、关键词检测器、回声消除和降噪等功能的工作原理,以及车辆系统的要求,如始终开启的麦克风输入流处理、连续回声消除和降噪等。更多相关信息可参考苹果开发者网站。

    蓝桥杯第十六届省赛真题!

    内容概要:本文档为第十六届蓝桥杯单片机设计与开发项目省赛的程序设计试题说明,面向大学组。文档详细规定了比赛的基本要求、硬件配置、功能描述、性能要求、输出控制、显示功能、按键功能及初始状态。参赛者需要使用指定的单片机竞赛实训平台,完成环境温度、光强、物体运动状态的检测,并通过数码管、LED指示灯、继电器等实现相应的数据显示、状态指示与控制功能。所有程序需在Keil环境下开发,并按要求提交工程文件。 适合人群:具有单片机编程基础的大专院校学生或相关专业技术人员。 使用场景及目标:①掌握单片机编程技能,熟悉传感器数据采集与处理;②学会通过数码管、LED、继电器等实现人机交互界面的设计与实现;③提高对硬件资源的有效利用能力,确保系统的实时性和稳定性。 阅读建议:此资源旨在帮助参赛者理解比赛规则和技术要求,建议仔细阅读各项功能的具体实现细节,特别注意硬件配置、性能指标以及提交规范的要求。同时,在实际操作中要严格按照文档中的规定进行开发和测试,确保作品符合评分标准。

    液压剪式升降平台(step SolidWorks)设计.rar

    液压剪式升降平台(step SolidWorks)设计.rar

    基于Python开发的一款简单易用的IT管理软件.zip

    基于Python开发的一款简单易用的IT管理软件.zip

    Day09【基于新闻事件的命名实体抽取】

    关于新闻事件的命名实体的训练集数据

Global site tag (gtag.js) - Google Analytics