url http ip port paht ? 数据
if 协议 IP PORT相同,同源
一,问题描述
django 创建2个项目
项目一,开启一个send_ajax请求 http://127.0.0.1:8000
访问正常
项目二,没有send_ajax请求 http://127.0.0.1:8010
那么这时候如果你通过ajax访问的 url:http://127.0.0.1:8000/send_ajax
浏览器会报错,内容是已拦截跨域请求,同源策略禁止读取位于http://127.0.0.1:8000/send_ajax远程资源,原因:cors头缺少 ‘Access-Control-Allow-Origin’
1.1 思考
jsonp是json用来跨域的一个东西。原理是通过script标签的跨域特性来绕过同源策略。
跨域请求:
ajax请求一定会被拦截
核心任务:跨域请求的是数据,数据,数据
通过引入jquery cdn 可以跨域 我们想 是不是script标签不会被拦截呢?
1.2跨域请求的演变
项目一 views
import json
def send_ajax(request):
return HttpResponse("yuan") # 第一次返回字符串
return HttpResponse("yuan()") # 第二次返回函数字符串
return HttpResponse("yuan('yuan')") # 第三次返回函数参数字符串
s='hello world'
return HttpResponse("yuan('%s')"%s) # 第四次返回函数字符串数据
s={"name":"egon","age":122}
return HttpResponse("%s('%s')"%(func_name,json.dumps(s))) # 第五次返回函数json字符串
项目二 html
第一次字符串,你要是知道数据是什么还请求干什么?所以这里只是个引子,告诉你可以这样做
yuan
第二次函数字符串
function yuan(){alert(123)}
第三次返回函数参数字符串
function yuan(arg){alert(arg)}
第四次返回函数字符串数据(数据也是字符串)
function yuan(arg){alert(arg)}
第五次返回函数json字符串
function yuan(arg){alert(Json.parse(arg))}
1.3问题
我不能硬生生的将写在html里面,我需要动态创建下面的函数
我们通过触发点击事件函数创建
function yuan(arg) {
console.log(arg);
console.log(JSON.parse(arg));
}
$(".send_ajax").click(function () {
kuayu_request("http://127.0.0.1:8000/send_ajax/")
});
function kuayu_request(url) {
var $script=$(""); // 创建script标签,是一个jquery对象:
$script.attr("src",url);
$("body").append($script);
$("body script:last").remove();
}
1.4 问题
1 问题函数名字是不是可以通过请求传送到后端呢?应该是同步的,可否通过回调函数?
可以通过发送请求的时候带着数据,数据包含你的函数名称,这样传到后端,再让后端返回你这个函数和数据,就可以执行了
项目二 html
$(".send_ajax").click(function () {
kuayu_request("http://127.0.0.1:8000/send_ajax/?callback=bar")
});
function kuayu_request(url) {
var $script=$(""); // 创建script标签,是一个jquery对象:
$script.attr("src",url);
$("body").append($script);
$("body script:last").remove();
}
项目一 views
def send_ajax(request):
func_name = request.GET.get('callback')
s = 'hello'
return HttpResponse("%s('%s')"%(func_name,json.dump(s)))
之前都是引子,下面才是真正的用法。。
ajax的跨域请求写法
$(".send_ajax").click(function () {
$.ajax({
url:"http://127.0.0.1:8000/send_ajax/",
success:function (data) {
alert(data)
},
// 跨域请求 告诉服务器我要什么类型的数据contenttype是告诉服务器我是什么类型数据
dataType:"jsonp",
jsonp: 'callbacks', //?callbacks=SayHi 相当于这个,问题就是在于前后端的函数名要相同
jsonpCallback:"SayHi"
})
});
function SayHi(arg) {
console.log("hello",arg)
}
{#// ==========================================基于jquery的JSONP的实现3 (推荐)#}
$(".send_ajax").click(function () {
$.ajax({
url:"http://127.0.0.1:8000/send_ajax/",
dataType:"jsonp", // 跨域请求
// callbacks=? ?就是随机字符串了,后端传回来运行的就是success函数,也就是funciton 函数参数是数据
jsonp: 'callbacks',
success:function (data) {
console.log(data)
}
})
});
jsonp的所有实现和应用例子
项目一的views.py
import json
def send_ajax(request):
s={"name":"egon","age":122}
return HttpResponse("list('%s')"%json.dumps(s))
项目二的index.html
Title项目2的首页
send_ajax
{#// ==========================================基于JS的JSONP的实现#}
function bar(arg) {
console.log(arg);
console.log(JSON.parse(arg));
}
$(".send_ajax").click(function () {
kuayu_request("http://127.0.0.1:8000/send_ajax/?callback=bar") // 回调函数
});
// 创建script添加scr属性,获取数据
function kuayu_request(url) {
var $script=$(""); // 创建script标签,是一个jquery对象:
$script.attr("src",url);
$("body").append($script);
$("body script:last").remove();
}
{#// ==========================================基于jquery的JSONP的实现1#}
$(".send_ajax").click(function () {
// getJSON帮助我们创建了script标签和src属性 ,还有个参数,data= 可以写入一些给后端的字符串
// 匿名函数,函数会有getJSON创建随机字符串也就是callbacks=?的问好的值,函数参数的data是数据
$.getJSON("http://127.0.0.1:8000/send_ajax/?callbacks=?",function (data) {
console.log(data)
})
})
{#// ==========================================基于jquery的JSONP的实现2#}
$(".send_ajax").click(function () {
$.ajax({
url:"http://127.0.0.1:8000/send_ajax/",
success:function (data) {
alert(data)
},
// 跨域请求 告诉服务器我要什么类型的数据contenttype是告诉服务器我是什么类型数据
dataType:"jsonp",
jsonp: 'callbacks', //?callbacks=SayHi 相当于这个,问题就是在于前后端的函数名要相同
jsonpCallback:"SayHi"
})
});
function SayHi(arg) {
console.log("hello",arg)
}
{#// ==========================================基于jquery的JSONP的实现3 (推荐)#}
$(".send_ajax").click(function () {
$.ajax({
url:"http://127.0.0.1:8000/send_ajax/",
dataType:"jsonp", // 跨域请求
// callbacks=? ?就是随机字符串了,后端传回来运行的就是success函数,也就是funciton 函数参数是数据
jsonp: 'callbacks',
success:function (data) {
console.log(data)
}
})
});
{#// =========================================应用#}
$(".send_ajax").click(function () {
$.ajax({
url:"http://www.jxntv.cn/data/jmd-jxtv2.html?callback=list&_=1454376870403",
dataType:"jsonp",
jsonp:"callback",
jsonpCallback:"list"
})
});
function list(shuju) {
console.log(shuju.data); // {data: Array(7)}
var data=shuju.data; // [{},{},{},......]
$.each(data,function (i,weekend) {
//console.log(weekend); // {week: "周日", list: Array(19)}
console.log(weekend.list); // {week: "周日", list: Array(19)}
var week= weekend.week;
$("body").append("
$.each(weekend.list,function (i,show) {
console.log(show); // {time: "", name: "《都市现场》90分钟直播版块", link: "http://www.jxntv.cn/live/jxtv2.shtml"}
var $a=$(""); //
$a.html(show.name);
$a.attr("href",show.link);
$("body").append('
');
$("body").append($a);
$("body").append('
');})
})
}
注意 JSONP一定是GET请求
CORS跨域资源共享(CORS,Cross-Origin Resource Sharing)
其本质是设置响应头,使得浏览器允许跨域请求。
项目一要访问项目二的视图,项目二的ajax请求代码如下
项目2的首页cors
send_ajax
$(".send_ajax").click(function () {
$.ajax({
// 这里我访问s1的的send_ajax
url:"http://127.0.0.1:8000/send_ajax/",
type:'GET', // head get post put delete
success:function (data) {
console.log(data);
console.log('')
}
})
})
项目二通过路由找到视图返回数据的代码如下
import json
def send_ajax(request):
# 授权的origin可以用*代替所有,methods可以多个,用逗号分开,简单的放一起,复杂放一起
if request.method == "OPTIONS": # 预检
response = HttpResponse()
response["Access-Control-Allow-Origin"] = "http://127.0.0.1:8011"
response["Access-Control-Allow-Methods"] = "PUT"
return response
elif request.method == "PUT": # 复杂请求,需要通过预检 put delete
s = {"name": "egon", "age": 122}
response = HttpResponse(json.dumps(s))
response["Access-Control-Allow-Origin"] = "http://127.0.0.1:8011"
return response
elif request.method == 'GET': # 简单强求 head get post
s = {"name": "egon", "age": 122}
response = HttpResponse(json.dumps(s))
response["Access-Control-Allow-Origin"] = "http://127.0.0.1:8011"
return response
流程:
项目二向项目一发送请求,项目一根据请求匹配路由规则,找到视图,视图首先返回给浏览器,如果没有cors就会被浏览器拦截,有了cors设置,浏览器就不会拦截cors设置的请求方式,最终
返回给项目一的数据,上述例子中,复杂请求(put,delete)先走预检,添加put请求,和允许访问的url,返回给浏览器,浏览器得到后在向服务器发送put请求,拿到数据,最后给项目一。