首页 > Web开发 > 详细

jsonp

时间:2017-02-05 17:51:03      阅读:264      评论:0      收藏:0      [点我收藏+]

1.JSONP原理剖析以及实现

1.1 同源策略限制

用django分别建立两个项目,jsonp01和jsonp02,然后再在这两个项目里分别建立一个app,比如名字叫jsonp1、jsonp2;jsonp01的端口号是8005,jsonp02的端口号是8006。

jsonp1的代码如下,

setting做常规配置;

urls.py,

urlpatterns = [
    url(r^admin/, admin.site.urls),
    url(r^testjsonp/, views.testjsonp),
    url(r^index/, views.index),
]

views.py,

def testjsonp(request):
    return HttpResponse(OK)


def index(request):
    return render(request,index.html)

index.html,

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <input type="button" onclick="ajaxjsonp1();" value="jsonp1" />

    <script src="/static/js/jquery-1.12.4.js"></script>
    <script>
        function ajaxjsonp1() {
            $.ajax({
                url : /testjsonp/,
                type : POST,
                data: {k1:v1},
                success : function (data) {
                    alert(data);
                }

            });
        }

    </script>
</body>
</html>

jsonp2的代码如下,

settings.py做常规配置;

urls.py,

urlpatterns = [
    url(r^admin/, admin.site.urls),
    url(r^testjsonp2/, views.testjsonp2),
]

views.py,

def testjsonp2(request):
    return HttpResponse(jsonp2ok)

如上面的代码,因为jsonp1请求的是自己的项目域名(url : ‘/testjsonp/‘),所以会如期收到返回的数据并alert(ok);

当把url : ‘/testjsonp/‘改成url : ‘http://10.103.9.83:8006/testjsonp2/‘,即用ajax实现跨域请求(好比在www.taobao.com上通过ajax访问www.jd.com的数据),则会报错如下图,

技术分享

这是因为自身浏览器的同源策略限制,比如在www.taobao.com上通过ajax访问www.jd.com的数据,该请求能从自己的浏览器发送到jd.com服务端,服务端也能处理并返回数据,但是当自己的浏览器发现收到的数据是非本机域名发来的,就会阻拦该数据,过程如下图,

技术分享,通过ajax,如果在当前域名去访问其他域名时,浏览器会出现同源策略限制,从而阻止请求的返回,所以无法用ajax实现跨域请求。

1.2 解决同源策略

img、script、iframe、link这些标签是不受同源策略限制的;src属性一般不鸟同源策略。利用这个特点,就可以实现jsonp的跨域请求。

改进jsonp1的index.html的代码,

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <input type="button" onclick="ajaxjsonp1();" value="jsonp1" />
    <input type="button" onclick="ajaxjsonp2();" value="jsonp2" />

    <script src="/static/js/jquery-1.12.4.js"></script>
    <script>
        function ajaxjsonp1() {
            $.ajax({
                url : http://10.103.9.83:8005 /testjsonp/,
                type : POST,
                data: {k1:v1},
                success : function (data) {
                    alert(data);
                }

            });
        }


        function ajaxjsonp2() {
#创建一个script标签,src值设置为要请求的域名,将这个标签加到head标签下,请求完之后remove掉这个标签。
            var tag = document.createElement("script");
            tag.src = "http://10.103.9.83:8006/testjsonp2/";
            document.head.appendChild(tag);
            document.head.removeChild(tag);
        }

    </script>
</body>
</html>

然后点击index.html的“jsonp2”按钮,就会收到如下报错:

技术分享,这说明本地浏览器已经收到服务端返回的数据(jsonp2ok)了,但是这个返回的数据是交给javascripts处理的,因为script里没有“jsonp2ok”这个方法,所以会报错“jsonp2ok没有定义”,所以需要在服务端和客户端再做一些修改,代码见下,

jsonp2的views.py,

import json
def testjsonp2(request):
    ll = [jack,luce,goi]

#直接返回一个jsonpfunc(ll),然后客户端的script标签里需要定义一个jsonpfunc方法,然后就能处理数据了。
    temp = jsonpfunc(%s) % (json.dumps(ll))
    return HttpResponse(temp)

jsonp1的index.html,

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <input type="button" onclick="ajaxjsonp1();" value="jsonp1" />
    <input type="button" onclick="ajaxjsonp2();" value="jsonp2" />

    <script src="/static/js/jquery-1.12.4.js"></script>
    <script>
        function ajaxjsonp1() {
            $.ajax({
                url : http://10.103.9.83:8005 /testjsonp/,
                type : POST,
                data: {k1:v1},
                success : function (data) {
                    alert(data);
                }

            });
        }


        function ajaxjsonp2() {
            var tag = document.createElement("script");
            tag.src = "http://10.103.9.83:8006/testjsonp2/";
            document.head.appendChild(tag);
            document.head.removeChild(tag);
        }
#收到服务端返回的数据,然后执行下面的jsonpfunc方法。
        function jsonpfunc(data) {
            console.log(data);
        }

    </script>
</body>
</html>

现在再点击jsonp1的index.html的"jsonp2"按钮,返回数据见下:

技术分享,客户端收到这些数据后,就可以处理了。

1.3 利用jquery实现伪ajax的跨域请求

上面讲的是jsonp的原理,原理就是利用那些不受同源策略限制的标签来发送请求,下面要说的是利用jquery实现伪ajax的跨域请求。

function weiajax(){
            $.ajax({
                url : http://www.jxntv.cn/data/jmd-jxtv2.html?callback=list&_=1454376870403,
                type : GET,
                dataType : jsonp,
                jsonp : callback,
                jsonpCallback : list
            });
        }

        function list(arg){
            console.log(arg);
        }

#这样就能获取到江西卫视的节目单了。
#注意,上面的function list(arg){}和 jsonpCallback : ‘list‘,之所以叫list,是因为江西卫视的服务器返回的数据中包含的javascript方法名叫list,所以我们也必须起名叫list,但是江西卫视是不规范的,规范的服务端应该是不限制客户端起什么方法名的;比如我本地有一个list方法,向江西卫视请求数据也需要定义一个list方法,那我岂不是要为了请求数据而将已有的list方法改名?显然是不合理的。但是江西卫视这么办了,我们就必须起这个名字。后面会讲到规范的方法。

 

如果是请求本地域名,就直接用ajax即可;如果是请求跨域数据,则依然用ajax,但是需要dataType : ‘jsonp‘、jsonp : ‘callback‘、jsonpCallback : ‘funcdemo‘,然后再定义一个function funcdemo(arg){}方法。

1.4 讲解jsonp : ‘callback‘、jsonpCallback : ‘funcdemo‘

如果服务端规范的话,则客户端处理返回数据的方法名是任意起的,比如客户端可以这样请求数据,

function weiajax(){
            $.ajax({
                url : http://www.jxntv.cn/data/jmd-jxtv2.html?callback=list&_=1454376870403,
                type : GET,
                dataType : jsonp,
                jsonp : callbackaaaaa,
                jsonpCallback : listqqqqq
            });
        }

        function listqqqqq(arg){
            console.log(arg);
        }
#如果服务端规范的话,则客户端任意起方法名都不会影响接收数据,原因下面会讲到。

jsonp2的views.py的代码修改如下,

import json
def testjsonp2(request):
    func = request.GET.get(callbackaaaaa)
    ll = [jack,luce,goi]

#之前方法名是固定的,现在把方法名设置为变量了,方法名就是取的客户端发来的值,所以客户端发什么值,服务端就将这个值作为方法名返回给客户端。
    temp = %s(%s) % (func,json.dumps(ll))
    return HttpResponse(temp)

虽然“jsonp : ‘callbackaaaaa‘,”可以随便定义,但是为了客户端和服务端的统一,我们约定设置为“jsonp : ‘callback‘”,不然比如客户端是callbackaaa,但是服务端是“request.GET.get(‘callbackbbb‘)”,那肯定不能返回数据给客户端;

只要服务端如jsonp2的views所示将返回的方法名设置为变量,则客户端进行ajax跨域请求时,就可以随便定义方法名,listqqqqq也行、ll44也行、funcdemo也行等等。

 1.5 jsonp不支持POST请求

jsonp的原理是利用那几个不受同源策略限制的标签的src属性来发送请求,比如<script src="http://www.baidu.com">,单单是写一个域名,所以肯定是GET请求,即使在$.ajax里指定了type:‘POST‘也不会起作用,本质上还是GET请求。

 

 

 

jsonp

原文:http://www.cnblogs.com/fuckily/p/6367995.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!