前端jsonp解决跨域问题
跨域问题的引入
在本地8000端口开启django程序,通过ajax往开启9000端口的django程序发送请求
8000端口的html文件
<input type="button" value="发送1" onclick="submitJsonp1();" />
<script src="/static/js/jquery-3.1.1.js"></script>
<script>
function submitJsonp1() {
$.ajax({
url: 'http://127.0.0.1:9000/ajax1.html',
type: 'GET',
data: {nid:2},
success:function (arg) {
$('#content').html(arg);
}
})
}
</script>
9000端口的接口
def ajax1(request):
ret = {'status':True, 'message': '....'}
import json
return HttpResponse(json.dumps(ret))
通过上图我们可以看到请求确确实实是发过去了,也拿到了结果。但是因为浏览器的同源策略结果没有拿到8000站点的范围里。
解决方式是利用src属性的跨域属性,程序员手动创建script标签,利用src属性去发请求,拿到请求结果后删除创建的这个script标签。
自定义script标签解决跨域
html
function submitJsonp2() {
var tag = document.createElement('script');
tag.src = 'http://127.0.0.1:9000/xiaokai.html';
document.head.appendChild(tag);
document.head.removeChild(tag);
}
views.py
def xiaokai(request):
return HttpResponse('ok')
我们发现返回的字符串已经到底script里面,此时script把ok当做一个变量,但是这个变量没有定义,所以报错。解决方式也很简单
后端返回的字符串ok用一个前端函数名包裹
def xiaokai(request):
return HttpResponse('func("ok")')
前端多定义一个函数
function fuck(arg) {
console.log(arg)
$('#content').html(arg);
}
此时console.log(arg) 就能正常显示字符串'ok' 了
利用ajax的jsonp
html
function submitJsonp4() {
$.ajax({
url: 'http://127.0.0.1:9000/xiaokai.html',
type: 'POST',
dataType: 'jsonp',
jsonp: 'callback',
jsonpCallback: 'func',
success: function (arg) {
console.log(arg)
}
})
}
真实发送的请求为http://127.0.0.1:9000/xiaokai.html?callback=func&_=1529415061035
定义success的好处是类似于匿名函数的概念,如果不设置success,那么就需要额外设置 jsonpCallback 指定的函数名,用了success就相当于万金油了
后端
def xiaokai(request):
func = request.GET.get('callback')
return HttpResponse('%s("xxoo")'%func)
jsonp的缺点
jsonp只能发get请求,要想支持所有的请求方式,需要用到cors