zoukankan      html  css  js  c++  java
  • Web高级 Ajax和跨域CORS

    Asynchronous JavaScript and XML

    1. XMLHttpRequest

    前端开发都知道,不多说。

    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function () {
    	if (xhr.readyState !== 4) return;
    	if (xhr.status >= 200 && xhr.status < 300) {
    		console.log(JSON.parse(xhr.responseText));
        }
        else {
    		// What to do when the request has failed
    		console.log('error', xhr);
    	}
    };
    xhr.open('GET', 'https://mysite.com/index');
    xhr.setRequestHeader('X-Token', '123456'); 
    xhr.send();
    

    1.1 open方法

    定义:open( Method, URL, Asynchronous, UserName, Password )
    - Method:GET/POST/HEAD/PUT/DELETE/OPTIONS
    - Asynchronous(defualt true)

    1.2 setRequestHeader方法

    定义:setRequestHeader( Name, Value )
    注意,以X开头的为header为自定义头部

    1.3 send方法

    定义:send(body)

    • body可以是:document,Blob, BufferSource, FormData, URLSearchParams, ReadableStream等

    2. Fetch

    新一代旨在替换XHR的API方法。

    fetch("https://mysite.com/index", {
      method: "POST",
      headers: {
        "Content-Type": "application/x-www-form-urlencoded",
        'X-Token': '123456'
      },
      body: "id=123"
    }).then(function (response) {
        if (response.ok) {
            return response.json();
        } else {
            return Promise.reject({
                status: response.status,
                statusText: response.statusText
            });
        }
    })
    .then(function (data) {
        console.log('success', data);
    })
    .catch(function (error) {
        console.log('error', error);
    });
    

    2.1 fetch方法

    定义:fetch(input, init)

    • input:URL或者Request对象
    • init:一个配置项对象,包括所有对请求的设置。可选的参数有:
      • method: 请求使用的方法,如 GET、POST。
      • headers: 请求的头信息,形式为 Headers 对象或 ByteString。
      • body: 请求的 body 信息:可能是一个 Blob、BufferSource、FormData、URLSearchParams 或者 USVString 对象。注意 GET 或 HEAD 方法的请求不能包含 body 信息。
      • mode: 请求的模式,如 cors、 no-cors 或者 same-origin。
      • credentials: 请求的 credentials,如 omit、same-origin 或者 include。
      • cache: 请求的 cache 模式: default, no-store, reload, no-cache, force-cache, or only-if-cached.

    2.2 回调

    fetch返回一个promise,采用then的链式调用避免回调地狱问题。

    2.3 返回值

    参考这里:https://developer.mozilla.org/zh-CN/docs/Web/API/Response

    3. XHR vs Fetch

    1. Fetch返回值不是可读的形式,需要使用response.json()转换为可读形式
    2. XHR的请求失败通过判断状态码,Fetch请求失败通过catch处理
    3. Fetch默认不带cookie,XHR默认带cookie
    4. Fetch在服务器返回 400,500 错误码时并不会reject而被当做成功处理进then,只有网络错误这些导致请求不能完成才会触发catch
    5. Fetch没有abort和onTimeout,不能中途中断,XHR可以。

    Cross-Origin Resource Sharing

    CORS是一种机制,用来保护跨域数据传输的安全性和降低风险。

    1. 常见的可以跨域请求的资源

    • XHR或Fetch发起的跨域HTTP请求
    • Web字体
    • CSS文件
    • Scripts文件

    2. 跨域相关的Http首部

    • Access-Control-Request-Headers
      (Preflight使用)客户端告诉服务器实际请求时使用的头部。

    • Access-Control-Request-Method
      (Preflight使用)客户端告诉服务器实际请求时使用的方法。

    • Access-Control-Allow-Origin
      服务端允许请求的源域

    • Access-Control-Allow-Credentials
      服务端是否允许请求带cookie,设置为true时allow-origin不能为*

    • Access-Control-Allow-Headers
      服务端允许的客户端请求的头部

    • Access-Control-Allow-Methods
      服务端允许客户端请求的方法

    • Access-Control-Max-Age
      preflight可以被缓存的时间

    • Cross-Origin-Resource-Policy
      (fetch使用)具体查看https://fetch.spec.whatwg.org/#cross-origin-resource-policy-header

    • Origin
      客户端请求从哪个域来

    1. OPTIONS /resources/post-here/ 
    2. HTTP/1.1
    3. Host: bar.other
    4. User-Agent: Mozilla/5.0 (Macintosh; U; 5.Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre
    6. Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    7. Accept-Language: en-us,en;q=0.5
    8. Accept-Encoding: gzip,deflate
    9. Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
    10. Connection: keep-alive
    11. Origin: http://foo.example
    12. Access-Control-Request-Method: POST
    13. Access-Control-Request-Headers: X-PINGOTHER, Content-Type
    
    //响应
    14. HTTP/1.1 200 OK
    15. Date: Mon, 01 Dec 2008 01:15:39 GMT
    16. Server: Apache/2.0.61 (Unix)
    17. Access-Control-Allow-Origin: http://foo.example
    18. Access-Control-Allow-Methods: POST, GET, OPTIONS
    19. Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
    20. Access-Control-Max-Age: 86400
    21. Vary: Accept-Encoding, Origin
    22. Content-Encoding: gzip
    23. Content-Length: 0
    24. Keep-Alive: timeout=2, max=100
    25. Connection: Keep-Alive
    26. Content-Type: text/plain
    
    

    3. 简单请求

    跨域请求分为简单请求和预检请求,全部符合下列条件时为简单请求:

    • 使用的方法为:GET/HEAD/POST
    • 不得设置安全首页之外的首页:Accept,Accept-Language,Content-Language,Content-Type,DPR,Downlink,Save-Data,Viewport-Width,Width
    • Content-Type只能是以下值: text/plain, multipart/form-data, application/x-www-form-urlencoded
    • 请求中的任意XMLHttpRequestUpload 对象均没有注册任何事件监听器
    • 请求中没有使用 ReadableStream 对象

    当使用普通请求时,如果服务器允许该源域跨域请求资源,则直接返回响应。如果服务器不允许跨域请求,则返回不正确的响应首部,则请求方不会收到任何数据。

    4. 预检请求(preflight request)

    除了简单请求的情况,其他的CORS请求都会有预检请求。
    预检请求会先使用OPTIONS方法发起一个预检请求到服务器,以获知服务器是否允许该实际请求,所以会进行2个回合的通信。

    典型的会触发预检请求的跨域情景:请求JSON数据 或 带有自定义头部
    如:

    • content-type:application/json
    • X-Audit-Token:X123456

    JSONP

    跨域请求的一种常见实现方式.

    1. 优缺点

    • 优点:
      不受同源策略限制,可以向没有启用CORS的跨域服务端请求数据。
      兼容性较强,所有浏览器都支持该技术。
    • 缺点
      只支持GET,不支持POST
      请求失败时不会有HTTP状态码返回
      安全性也是一个值得考虑的问题

    2. 实现原理

    1. Client端用JS动态生成一个script标签并添加到文档流中,如
    <script type="text/javascript">
      function jsonpCallBack(data){
            console.log(data.msg);
      }
      $(document).ready(function(){
            $("body").append('<script src="http://www.ASite.com/ServerJSONP.js?callback=jsonpCallBack"></script>');
        });
    </script>
    
    1. 浏览器会使用GET方法请求ASite上的ServerJSONP.js并携带参数
    2. 服务端接收到该请求,并根据参数中的回调函数名动态生成返回的内容,如
    jsonpCallBack({msg:"this is jsonp request!"});
    
    1. 浏览器获取到script标签请求的内容后会执行其中的代码
    2. 最终我们定义的jsonpCallBack函数会被调用,输出: "this is jsonp request!"

    refs:
    https://xhr.spec.whatwg.org/
    https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest
    https://gomakethings.com/why-i-still-use-xhr-instead-of-the-fetch-api/
    https://hacks.mozilla.org/2015/03/this-api-is-so-fetching/
    https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS

  • 相关阅读:
    Jenkins入门教程(3)
    Jenkins入门教程(2)
    Jenkins入门教程(1)
    Tomcat与Weblogic
    fidder教程
    postman教程(3)- 用Postman生成Request代码
    postman教程(2)— 在test suite中运行test case
    postman教程(1)
    unix环境高级编程——文件和目录
    unix环境高级编程——文件IO
  • 原文地址:https://www.cnblogs.com/full-stack-engineer/p/9818697.html
Copyright © 2011-2022 走看看