ajax跨域请求

一、Access-Control-Allow-Origin

一个html页面,输入两个数字,点击提交,后台返回这两个数字之和。
index.html

<html>

<head>
    <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
</head>

<body>
    <input id='x' type='text' value="432"></input>
    <input id='y' type='text' value="234"></input>
    <button id="submit">提交</button>
    <h1 id='resp'></h1>
</body>
<script type="text/javascript">
    $('#submit').click(function(event) {
        $.get('http://localhost:5000/add', {
            x: $("#x").val(),
            y: $("#y").val()
        }, function(data) {
            console.log(data)
            $("#resp").text(data)
            console.log('get over')
        })
    });
</script>

</html>

用flask编一个服务器端程序,来回复上述html中的请求。
server.py

from flask import  Flask,request,make_response
app=Flask(__name__)
@app.route("/add")
def add():
    x,y=map(int,map(request.args.get,"xy"))
    print(add.__name__,x,y)
    resp=make_response(str(x+y))
    resp.headers['Access-Control-Allow-Origin']="*"
    return resp
if __name__ == '__main__':
    app.run(debug=True)
    

使用live-server作为静态服务器在index.html所在文件夹启动,默认端口为8080。
使用python server.py 启动flask程序,默认端口为5000。

关于此程序有如下知识点:

  • 浏览器是阻止跨域请求的
    这种阻止只是禁止用户查看返回结果,而不是js无法发出请求。
    实际上,后台已经收到了js发出的请求,并且成功进行了回复,只是请求结果传到浏览器之后,浏览器禁止js获取返回的数据。
    所以,写爬虫的时候从来没有遇到过无法获取返回数据的问题。
  • 是否允许浏览器展示返回结果,这项权限是由后台程序控制的
    如果后台程序的回复头部的Access-Control-Allow-Origin包括当前页面的域名,则浏览器将返回结果进行展示,否则不予展示。
  • Access-Control-Allow-Origin只允许等于一个字符串值,而不允许一个域名列表
    后台程序可以获取请求程序的主机名,进而决定是否允许浏览器展示自己的返回结果。如果允许,添加Access-Control-Allow-Origin头部即可。

下面大致描述一下这些CORS(Cross Origin Resource Share,跨域资源共享)响应头的意义:

  • Access-Control-Allow-Origin:允许访问的客户端域名,例如:http://web.xxx.com,若为*,则表示从任意域都能访问,即不做任何限制。
  • Access-Control-Allow-Methods:允许访问的方法名,多个方法名用逗号分割,例如:GET,POST,PUT,DELETE,OPTIONS。
  • Access-Control-Allow-Credentials:是否允许请求带有验证信息,若要获取客户端域下的cookie时,需要将其设置为true。
  • Access-Control-Allow-Headers:允许服务端访问的客户端请求头,多个请求头用逗号分割,例如:Content-Type。
  • Access-Control-Expose-Headers:允许客户端访问的服务端响应头,多个响应头用逗号分割。

需要注意的是,CORS规范中定义Access-Control-Allow-Origin只允许两种取值,要么为*,要么为具体的域名,也就是说,不支持同时配置多个域名。为了解决跨多个域的问题,需要在代码中做一些处理,这里将Filter初始化参数作为一个域名的集合(用逗号分隔),只需从当前请求中获取Origin请求头,就知道是从哪个域中发出的请求,若该请求在以上允许的域名集合中,则将其放入Access-Control-Allow-Origin响应头,这样跨多个域的问题就轻松解决了。

二、jsonp

在编写html页面时,html页面的head部分通常包含很多js库,这是通过script标签引入的,例如:

<head>
    <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
</head>

可以直接引入外部的JS,所以加载JS是没有跨域请求这一说的。
于是,我们可以在后台编写一段JS,从而控制前端DOM。
server.py

from flask import  Flask,request,make_response
app=Flask(__name__) 
@app.route("/useJsonp")
def useJsonp():
    return r"$('#resp').text('jsonp is ok')"
if __name__ == '__main__':
    app.run(debug=True)
    

index.html

<html>

<head>
    <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
</head>

<body>
    <h1 id='resp'></h1>
</body>
<script type="text/javascript" src="http://localhost:5000/useJsonp">
</script>

</html>

参考资料

http://blog.csdn.net/shaobingj126/article/details/49420145
http://www.cnblogs.com/weidiao/p/5517151.html

原文地址:https://www.cnblogs.com/weiyinfu/p/7927966.html