AJAX請求和跨域請求詳解(原生JS、Jquery)

1、概述

AJAX 是一種在無需從新加載整個網頁的狀況下,可以更新部分網頁的技術。javascript

AJAX = 異步 JavaScript 和 XML,是一種用於建立快速動態網頁的技術。經過在後臺與服務器進行少許數據交換,AJAX 可使網頁實現異步更新。這意味着能夠在不從新加載整個網頁的狀況下,對網頁的某部分進行更新。傳統的網頁(不使用 AJAX)若是須要更新內容,必需重載整個網頁面。html

本博客實驗環境:前端

python:2.7.11
web框架:tonado
jquery:2.1.1

 

2、「僞」AJAX

因爲HTML標籤的iframe標籤具備局部加載內容的特性,因此可使用其來僞造Ajax請求,從而實現頁面異步更新。java

<!DOCTYPE html>
<html>

    <head lang="en">
        <meta charset="UTF-8">
        <title></title>
    </head>

    <body>

        <div>
            <!--時間戳不變表明整個頁面不刷新-->
            <p>頁面時間戳:<span id="currentTime"></span></p>
            <p>請輸入要加載的地址:</p>
            <p>
                <input id="url" type="text" />
                <input type="button" value="刷新" onclick="LoadPage();">
            </p>
        </div>


        <div>
            <h3>加載頁面位置:</h3>
            <iframe id="iframePosition" style="width: 100%;height: 500px;"></iframe>
        </div>


        <script type="text/javascript">

            window.onload= function(){
                var myDate = new Date();
                document.getElementById('currentTime').innerText = myDate.getTime();

            };

            function LoadPage(){
                var targetUrl =  document.getElementById('url').value;
//                爲iframe的src動態賦值
                document.getElementById("iframePosition").src = targetUrl;
            }

        </script>

    </body>
</html>
「僞」AJAX實例

 

3、原生AJAX

Ajax主要就是使用 【XmlHttpRequest】對象來完成請求的操做,該對象在主流瀏覽器中均存在(除早期的IE),Ajax首次出現IE5.5中存在(ActiveX控件)。python

一、XmlHttpRequest對象介紹

XmlHttpRequest對象的主要方法:jquery

a. void open(String method,String url,Boolen async)
   用於建立請求
    
   參數:
       method: 請求方式(字符串類型),如:POST、GET、DELETE...
       url:    要請求的地址(字符串類型)
       async:  是否異步(布爾類型),通常填true
 
b. void send(String body)
    用於發送請求
 
    參數:
        body: 要發送的數據(字符串類型)
 
c. void setRequestHeader(String header,String value)
    用於設置請求頭
 
    參數:
        header: 請求頭的key(字符串類型)
        vlaue:  請求頭的value(字符串類型)
 
d. String getAllResponseHeaders()
    獲取全部響應頭
 
    返回值:
        響應頭數據(字符串類型)
 
e. String getResponseHeader(String header)
    獲取響應頭中指定header的值
 
    參數:
        header: 響應頭的key(字符串類型)
 
    返回值:
        響應頭中指定的header對應的值
 
f. void abort()
 
    終止請求

 

XmlHttpRequest對象的主要屬性:web

a. Number readyState
   狀態值(整數)
 
   詳細:
      0-未初始化,還沒有調用open()方法;
      1-啓動,調用了open()方法,未調用send()方法;
      2-發送,已經調用了send()方法,未接收到響應;
      3-接收,已經接收到部分響應數據;
      4-完成,已經接收到所有響應數據;
 
b. Function onreadystatechange
   當readyState的值改變時自動觸發執行其對應的函數(回調函數)
 
c. String responseText
   服務器返回的數據(字符串類型)
 
d. XmlDocument responseXML
   服務器返回的數據(Xml對象)
 
e. Number states
   狀態碼(整數),如:200、404...
 
f. String statesText
   狀態文本(字符串),如:OK、NotFound...

二、跨瀏覽器支持

XmlHttpRequest支持:
IE7+, Firefox, Chrome, Opera, etc.ajax

IE6, IE5不支持XmlHttpRequest。,因此使用ActiveXObject("Microsoft.XMLHTTP")對象實現。json

原生AJAX實例(支持XHR和ActiveXObject):後端

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>

    <h1>XMLHttpRequest - Ajax請求</h1>
    <input type="button" onclick="XhrGetRequest();" value="Get發送請求" />
    <input type="button" onclick="XhrPostRequest();" value="Post發送請求" />

    <script type="text/javascript">

        function GetXHR(){
            var xhr = null;
            if(XMLHttpRequest){
                xhr = new XMLHttpRequest();
            }else{
                xhr = new ActiveXObject("Microsoft.XMLHTTP");
            }
            return xhr;

        }

        function XhrPostRequest(){
            var xhr = GetXHR();
            // 定義回調函數
            xhr.onreadystatechange = function(){
                if(xhr.readyState == 4){
                    // 已經接收到所有響應數據,執行如下操做
                    var data = xhr.responseText;
                    alert(data);
                }
            };
            // 指定鏈接方式和地址----文件方式
            xhr.open('POST', "/test", true);
            // 設置請求頭
            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset-UTF-8');
            // 發送請求
            xhr.send('n1=1;n2=2;');
        }

        function XhrGetRequest(){
            var xhr = GetXHR();
            // 定義回調函數
            xhr.onreadystatechange = function(){
                if(xhr.readyState == 4){
                    // 已經接收到所有響應數據,執行如下操做
                    var data = xhr.responseText;
                    alert(data);
                }
            };
            // 指定鏈接方式和地址----文件方式
            xhr.open('get', "/test", true);
            // 發送請求
            xhr.send();
        }

    </script>

</body>
</html>
原生AJAX前端代碼
#! /usr/bin/env python
# -*- coding:utf-8 -*-
# __author__ = "TKQ"
#! /usr/bin/env python
# -*- coding:utf-8 -*-
# __author__ = "TKQ"
import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web

from tornado.options import define, options
define("port", default=8888, help="run on the given port", type=int)

class IndexHandler(tornado.web.RequestHandler):
    def get(self):
        self.render("AJAX.html")

class TestHandler(tornado.web.RequestHandler):
    def get(self):
        self.write("hello ajax get method!")
    def post(self):
        n1=self.get_argument("n1")
        n2=self.get_argument("n2")
        addvalue=int(n1)+int(n2)
        self.write("n1+n2=%s"%addvalue)



if __name__ == "__main__":
    tornado.options.parse_command_line()
    app = tornado.web.Application(
        handlers=[(r"/", IndexHandler),
                  (r"/test",TestHandler)]
    ,template_path="template")

    http_server = tornado.httpserver.HTTPServer(app)
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.instance().start()
後端tornado代碼

 

4、jQuery Ajax

jQuery其實就是一個JavaScript的類庫,其將複雜的功能作了上層封裝,使得開發者能夠在其基礎上寫更少的代碼實現更多的功能。

  • jQuery 不是生產者,而是大天然搬運工。
  • jQuery Ajax本質 XMLHttpRequest 或 ActiveXObject 

注:2.+版本再也不支持IE9如下的瀏覽器

jQuery.ajax(...)

    部分參數:

            url:請求地址
           type:請求方式,GET、POST(1.9.0以後用method)
        headers:請求頭
           data:要發送的數據
    contentType:即將發送信息至服務器的內容編碼類型(默認: "application/x-www-form-urlencoded; charset=UTF-8")
          async:是否異步
        timeout:設置請求超時時間(毫秒)

     beforeSend:發送請求前執行的函數(全局)
       complete:完成以後執行的回調函數(全局)
        success:成功以後執行的回調函數(全局)
          error:失敗以後執行的回調函數(全局)
    

        accepts:經過請求頭髮送給服務器,告訴服務器當前客戶端課接受的數據類型
       dataType:將服務器端返回的數據轉換成指定類型
                       "xml": 將服務器端返回的內容轉換成xml格式
                      "text": 將服務器端返回的內容轉換成普通文本格式
                      "html": 將服務器端返回的內容轉換成普通文本格式,在插入DOM中時,若是包含JavaScript標籤,則會嘗試去執行。
                    "script": 嘗試將返回值看成JavaScript去執行,而後再將服務器端返回的內容轉換成普通文本格式
                      "json": 將服務器端返回的內容轉換成相應的JavaScript對象
                     "jsonp": JSONP 格式
                              使用 JSONP 形式調用函數時,如 "myurl?callback=?" jQuery 將自動替換 ? 爲正確的函數名,以執行回調函數

                      若是不指定,jQuery 將自動根據HTTP包MIME信息返回相應類型(an XML MIME type will yield XML, in 1.4 JSON will yield a JavaScript object, in 1.4 script will execute the script, and anything else will be returned as a string

     converters: 轉換器,將服務器端的內容根據指定的dataType轉換類型,並傳值給success回調函數
             $.ajax({
                  accepts: {
                    mycustomtype: 'application/x-some-custom-type'
                  },
                  
                  // Expect a `mycustomtype` back from server
                  dataType: 'mycustomtype'

                  // Instructions for how to deserialize a `mycustomtype`
                  converters: {
                    'text mycustomtype': function(result) {
                      // Do Stuff
                      return newresult;
                    }
                  },
                });
Jquery底層AJAX方法
jQuery.get(...)
    全部參數:
         url: 待載入頁面的URL地址
        data: 待發送 Key/value 參數。
     success: 載入成功時回調函數。
    dataType: 返回內容格式,xml, json,  script, text, html


jQuery.post(...)
    全部參數:
         url: 待載入頁面的URL地址
        data: 待發送 Key/value 參數
     success: 載入成功時回調函數
    dataType: 返回內容格式,xml, json,  script, text, html


jQuery.getJSON(...)
    全部參數:
         url: 待載入頁面的URL地址
        data: 待發送 Key/value 參數。
     success: 載入成功時回調函數。


jQuery.getScript(...)
    全部參數:
         url: 待載入頁面的URL地址
        data: 待發送 Key/value 參數。
     success: 載入成功時回調函數。
封裝請求方法的AJAX方法

Jquery AJAX實例:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>

    <p>
        <input type="button" onclick="JqSendRequest();" value='Ajax請求' />
    </p>


    <script type="text/javascript" src='{{static_url("jquery-2.1.1.min.js")}}'></script>
    <script>

        function JqSendRequest(){
            $.ajax({
                url: "/test",
                type: 'GET',
                dataType: 'text',
                success: function(data, statusText, xmlHttpRequest){
                    console.log(data, statusText, xmlHttpRequest)
                }
            })
        }
    </script>
</body>
</html>
Jquery實例前端
#! /usr/bin/env python
# -*- coding:utf-8 -*-
# __author__ = "TKQ"
#! /usr/bin/env python
# -*- coding:utf-8 -*-
# __author__ = "TKQ"
import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web

from tornado.options import define, options
define("port", default=8888, help="run on the given port", type=int)

class IndexHandler(tornado.web.RequestHandler):
    def get(self):
        self.render("JQ.html")

class TestHandler(tornado.web.RequestHandler):
    def get(self):
        self.write("hello ajax get method!")
    def post(self):
        n1=self.get_argument("n1")
        n2=self.get_argument("n2")
        addvalue=int(n1)+int(n2)
        self.write("n1+n2=%s"%addvalue)



if __name__ == "__main__":
    tornado.options.parse_command_line()
    app = tornado.web.Application(
        handlers=[(r"/", IndexHandler),
                  (r"/test",TestHandler)]
    ,template_path="template",static_path= 'statics')

    http_server = tornado.httpserver.HTTPServer(app)
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.instance().start()
後端tornado代碼

 

5、跨域AJAX

因爲瀏覽器存在同源策略機制,同源策略阻止從一個源加載的文檔或腳本獲取或設置另外一個源加載的文檔的屬性。

關於同源的斷定規則:若是兩個頁面擁有相同的協議(protocol),端口(若是指定),和主機,那麼這兩個頁面就屬於同一個源(origin)。

URL 結果 緣由
http://store.company.com/dir/page.html 參照對象
http://store.company.com/dir2/other.html 成功  
http://store.company.com/dir/inner/another.html 成功  
https://store.company.com/secure.html 失敗 協議不一樣
http://store.company.com:81/dir/etc.html 失敗 端口不一樣
http://news.company.com/dir/other.html 失敗 主機名不一樣

 

特別的:因爲同源策略是瀏覽器的限制,因此請求的發送和響應是能夠進行,只不過瀏覽器不接受罷了。

瀏覽器同源策略並非對全部的請求均制約:

  • 制約: XmlHttpRequest
  • 無效: img、iframe、script等具備src屬性的標籤

 

那麼若有解決跨域請求的問題呢?下面提供了兩中方法實現跨域請求,分別是JSONP和CORS。

Jsonp 與 CORS 的比較:

  • Jsonp只支持 GET 請求,CORS支持全部類型的HTTP請求。
  • Jsonp 的優點在於支持老式瀏覽器,以及能夠向不支持CORS的網站請求數據。

一、JSONP實現跨域請求

JSONP(JSONP - JSON with Padding是JSON的一種「使用模式」),利用script標籤的src屬性(瀏覽器容許script標籤跨域)。

基本原理,經過如下幾步完成跨域請求:

  一、brower建立script標籤,並利用script標籤的src屬性發送跨域請求,獲取服務器的返回值在<script>標籤內。
  二、server返回函數調用語句(myfunc(args);),並將須要返回的值(args)做爲函數參數一併返回。

  三、brower執行服務器返回的調用函數的語句(myfunc(args)),對返回值進行操做。

  四、brower刪除第一步建立的script標籤。

 

 

 JSONP實例一,固定回調函數名:

#! /usr/bin/env python
# -*- coding:utf-8 -*-
# __author__ = "TKQ"
import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web

from tornado.options import define, options
define("port", default=8000, help="run on the given port", type=int)

class IndexHandler(tornado.web.RequestHandler):
    def get(self):
        self.render("jsonp.html")

class TestHandler(tornado.web.RequestHandler):
    def get(self):
        #客戶端定義的函數名必須也爲myfunc纔會調用
        self.write("myfunc([1,2,3]);")

if __name__ == "__main__":
    tornado.options.parse_command_line()
    app = tornado.web.Application(
        handlers=[(r"/", IndexHandler),
                  (r"/test",TestHandler)]
    ,template_path="template",static_path= 'statics')

    http_server = tornado.httpserver.HTTPServer(app)
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.instance().start()
後端tornado代碼
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>

    <p>
        <input type="button" onclick="GetJsonp();"  value='提交'/>
    </p>

    <!--<script type="text/javascript" src='{{static_url("jquery-2.1.1.min.js")}}'></script>-->
    <script>
//        建立script標籤跨域請求,並根據返回函數myfunc([1,2,3]);執行定義的myfunc函數
        function GetJsonp(){
            var tag = document.createElement('script');
            tag.src = "http://tkq2.com:8000/test";
            document.head.appendChild(tag);
            document.head.removeChild(tag);
        }
        function  myfunc(list) {
            console.log(list);
        }


    </script>
</body>
</html>
原生jsonp實例
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>

    <p>
        <input type="button" onclick="GetJsonp();"  value='提交'/>
    </p>

    <script type="text/javascript" src='{{static_url("jquery-2.1.1.min.js")}}'></script>
    <script>
//        建立script標籤跨域請求,並根據返回函數myfunc([1,2,3]);執行定義的myfunc函數

        function GetJsonp(){
            $.ajax({
                url: "http://tkq2.com:8000/test",
                dataType: 'jsonp',
                jsonpCallback:'myfunc'  //自定義了回調函數名,默認爲jQuery自動生成的隨機函數名。若是不寫回調函數名,默認執行與服務器返回的函數名相同的函數。

            })
        }
//      回調函數
        function  myfunc(list) {
            console.log(list);
        }

    </script>
</body>
</html>
Jquery的jsonp實例

JSONP實例二,可變回調函數名: 

實例一中,回調函數服務器端定寫死了,請求端必須定義和服務器端相同函數名才行。但做爲服務端應該有更好的兼容性,請求端自行決定回調函數名字,下面咱們來實現這個功能。

原理:http://tkq2.com:8000/test?jsonpcallback=myfunc,經過請求中攜帶jsonpcallback=myfunc參數,使服務端獲取到自定義的回調函數名。

#! /usr/bin/env python
# -*- coding:utf-8 -*-
# __author__ = "TKQ"
import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web

from tornado.options import define, options
define("port", default=8000, help="run on the given port", type=int)

class IndexHandler(tornado.web.RequestHandler):
    def get(self):
        self.render("jq_jsonp.html")

class TestHandler(tornado.web.RequestHandler):
    def get(self):
        func_name=self.get_argument('jsonpcallback')
        self.write("%s([1,2,3]);" %func_name)
if __name__ == "__main__":
    tornado.options.parse_command_line()
    app = tornado.web.Application(
        handlers=[(r"/", IndexHandler),
                  (r"/test",TestHandler)]
    ,template_path="template",static_path= 'statics')

    http_server = tornado.httpserver.HTTPServer(app)
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.instance().start()
後端tornado代碼
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>

    <p>
        <input type="button" onclick="GetJsonp();"  value='提交'/>
    </p>

    <!--<script type="text/javascript" src='{{static_url("jquery-2.1.1.min.js")}}'></script>-->
    <script>
//        建立script標籤跨域請求,並根據返回函數myfunc([1,2,3]);執行定義的myfunc函數
        function GetJsonp(){
            var tag = document.createElement('script');
//自定義回調函數名,jsonpcallback=myfunc字段供服務端讀取。
            tag.src = "http://tkq2.com:8000/test?jsonpcallback=myfunc";
            document.head.appendChild(tag);
            document.head.removeChild(tag);
        }
        function  myfunc(list) {
            console.log(list);
        }
原生JS實現
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>

    <p>
        <input type="button" onclick="GetJsonp();"  value='提交'/>
    </p>

    <script type="text/javascript" src='{{static_url("jquery-2.1.1.min.js")}}'></script>
    <script>
//        建立script標籤跨域請求,並根據返回函數myfunc([1,2,3]);執行定義的myfunc函數

        function GetJsonp(){
            $.ajax({
                url: "http://tkq2.com:8000/test",
                dataType: 'jsonp',
                jsonp:'jsonpcallback',   //傳遞給請求處理程序或頁面的,用以得到jsonp回調函數名的參數名(通常默認爲:callback)
                jsonpCallback:'myfunc'  //自定義了回調函數名,默認爲jQuery自動生成的隨機函數名。若是不寫回調函數名,默認執行與服務器返回的函數名相同的函數。

            })
        }
//      回調函數
        function  myfunc(list) {
            console.log(list);
        }

    </script>
</body>
</html>
Jquery實現

JSONP實例三,江西衛視節目單獲取:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>

    <p>
        <input type="button" onclick="GetJsonp();"  value='JS提交'/>
        <input type="button" onclick="JQJsonp();"  value='JQ提交'/>
    </p>
    <script type="text/javascript" src='{{static_url("jquery-2.1.1.min.js")}}'></script>
    <script>
        //回調函數
        function  list(data) {
            console.log(data);
        }
        function GetJsonp(){
            var tag = document.createElement('script');
            tag.src = "http://www.jxntv.cn/data/jmd-jxtv2.html";
            document.head.appendChild(tag);
            document.head.removeChild(tag);
        }
        function JQJsonp(){
            $.ajax({
                url: "http://www.jxntv.cn/data/jmd-jxtv2.html",
                dataType: 'jsonp',
                jsonpCallback:'list'

            })
        }

    </script>
</body>
</html>
江西衛視節目單獲取

 

 

二、CORS跨域資源共享

 隨着技術的發展,如今的瀏覽器能夠支持主動設置從而容許跨域請求,即:跨域資源共享(CORS,Cross-Origin Resource Sharing),其本質是設置響應頭,使得瀏覽器容許跨域請求。

這種實現方式:請求端和普通的AJAX方法相同,但服務器端須要作相應的配置。

 簡單請求 OR 非簡單請求

條件:
    1、請求方式:HEAD、GET、POST
    2、請求頭信息:
        Accept
        Accept-Language
        Content-Language
        Last-Event-ID
        Content-Type 對應的值是如下三個中的任意一個
                                application/x-www-form-urlencoded
                                multipart/form-data
                                text/plain
 
注意:同時知足以上兩個條件時,則是簡單請求,不然爲複雜請求

CORS中簡單請求和非簡單請求的區別是什麼?

簡單請求:一次請求
非簡單請求:兩次請求,在發送數據以前會先發一次請求用於作「預檢」,只有「預檢」經過後纔再發送一次請求用於數據傳輸。 

關於「預檢」

- 請求方式:OPTIONS
- 「預檢」其實作檢查,檢查若是經過則容許傳輸數據,檢查不經過則再也不發送真正想要發送的消息
- 如何「預檢」
     => 若是複雜請求是PUT等請求,則服務端須要設置容許某請求,不然「預檢」不經過
        Access-Control-Request-Method
     => 若是複雜請求設置了請求頭,則服務端須要設置容許某請求頭,不然「預檢」不經過
        Access-Control-Request-Headers

基於cors實現AJAX請求:

a、支持跨域,簡單請求

服務器設置響應頭:Access-Control-Allow-Origin = '域名' 或 '*'

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>

    <h1>CORS</h1>
    <input type="button" onclick="XhrGetRequest();" value="Get發送請求" />

    <script type="text/javascript">
        function XhrGetRequest(){
            var xhr =new XMLHttpRequest();
            xhr.onreadystatechange = function(){
                if(xhr.readyState == 4){
                    var data = xhr.responseText;
                    alert(data);
                }
            };
            xhr.open('get', "http://tkq2.com:8000/test", true);
            xhr.send();
        }
    </script>

</body>
</html>
HTML+JS
tonado設置:
class TestHandler(tornado.web.RequestHandler):
    def get(self):
        self.set_header('Access-Control-Allow-Origin', "http://tkq1.com:8000")
        self.write('cors get success')

b、支持跨域,複雜請求

因爲複雜請求時,首先會發送「預檢」請求,若是「預檢」成功,則發送真實數據。

  • "預檢「請求前,先須要設置預檢接收源地址:Access-Control-Allow-Origin
  • 「預檢」請求時,容許請求方式則需服務器設置響應頭:Access-Control-Request-Method
  • 「預檢」請求時,容許請求頭則需服務器設置響應頭:Access-Control-Request-Headers
  • 「預檢」緩存時間,服務器設置響應頭:Access-Control-Max-Age

預檢完成後,在發送負載請求,例如put方法,該方法如同簡單方法同樣,須要設置接收源地址:Access-Control-Allow-Origin

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>

    <h1>CORS</h1>
    <input type="button" onclick="XhrGetRequest();" value="put發送請求js" />
    <input type="button" onclick="JqSendRequest();" value="put發送請求jq" />
    
    <script type="text/javascript" src='{{static_url("jquery-2.1.1.min.js")}}'></script>
    <script type="text/javascript">
        function XhrGetRequest(){
            var xhr =new XMLHttpRequest();
            xhr.onreadystatechange = function(){
                if(xhr.readyState == 4){
                    var data = xhr.responseText;
                    alert(data);
                }
            };
            xhr.open('put', "http://tkq2.com:8000/cors", true);
            xhr.setRequestHeader('h1', 'v1');
            xhr.send();
        }

        function JqSendRequest(){
            $.ajax({
                url: "http://tkq2.com:8000/cors",
                type: 'PUT',
                dataType: 'text',
                headers: {'h1': 'v1'},
                success: function(data, statusText, xmlHttpRequest){
                    alert(data);
                }
            })
        }
    </script>

</body>
</html>
HTML+JS
class CORSHandler(tornado.web.RequestHandler):
    # 複雜請求方法put
    def put(self):
        self.set_header('Access-Control-Allow-Origin', "http://tkq1.com:8000")
        self.write('put success')
    # 預檢方法設置
    def options(self, *args, **kwargs):
        #設置預檢方法接收源
        self.set_header('Access-Control-Allow-Origin', "http://tkq1.com:8000")
        #設置預複雜方法自定義請求頭h1和h2
        self.set_header('Access-Control-Allow-Headers', "h1,h2")
        #設置容許哪些複雜請求方法
        self.set_header('Access-Control-Allow-Methods', "PUT,DELETE")
        #設置預檢緩存時間秒,緩存時間內發送請求無需再預檢
        self.set_header('Access-Control-Max-Age', 10)

c、跨域獲取響應頭

默認獲取到的全部響應頭只有基本信息,若是想要獲取自定義的響應頭,則須要再服務器端設置Access-Control-Expose-Headers。

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>

    <h1>CORS</h1>
    <input type="button" onclick="XhrGetRequest();" value="put發送請求js" />
    <input type="button" onclick="JqSendRequest();" value="put發送請求jq" />

    <script type="text/javascript" src='{{static_url("jquery-2.1.1.min.js")}}'></script>
    <script type="text/javascript">
        function XhrGetRequest(){
            var xhr =new XMLHttpRequest();
            xhr.onreadystatechange = function(){
                if(xhr.readyState == 4){
                    var data = xhr.responseText;
                    alert(data);
                    // 獲取響應頭
                    console.log(xhr.getAllResponseHeaders());
                }
            };
            xhr.open('put', "http://tkq2.com:8000/cors", true);
            xhr.setRequestHeader('h1', 'v1');
            xhr.send();
        }

        function JqSendRequest(){
            $.ajax({
                url: "http://tkq2.com:8000/cors",
                type: 'PUT',
                dataType: 'text',
                headers: {'h1': 'v1'},
                success: function(data, statusText, xmlHttpRequest){
                    alert(data);
                    // 獲取響應頭    Content-Type: text/html; charset=UTF-8  Cos2: cos_value2    Cos1: cos_value1
                    console.log(xmlHttpRequest.getAllResponseHeaders());

                }
            })
        }
    </script>

</body>
</html>
HTML+JS  
class CORSHandler(tornado.web.RequestHandler):
    # 複雜請求方法put
    def put(self):
        self.set_header('Access-Control-Allow-Origin', "http://tkq1.com:8000")
        # 自定義header
        self.set_header('cos1', "cos_value1")
        self.set_header('cos2', "cos_value2")
        #設置容許請求端接收自定義的請求頭,不然請求段沒法接收自定義的請求頭 self.set_header('Access-Control-Expose-Headers', "cos1,cos2")
        self.write('put success')
    # 預檢方法設置
    def options(self, *args, **kwargs):
        self.set_header('Access-Control-Allow-Origin', "http://tkq1.com:8000")
        self.set_header('Access-Control-Allow-Headers', "h1,h2")
        self.set_header('Access-Control-Allow-Methods', "PUT,DELETE")
        self.set_header('Access-Control-Max-Age', 10) 

d、跨域傳輸cookie

在跨域請求中,默認狀況下,HTTP Authentication信息,Cookie頭以及用戶的SSL證書不管在預檢請求中或是在實際請求都是不會被髮送。

若是想要發送:

  • 瀏覽器端:XMLHttpRequest的withCredentials爲true
  • 服務器端:Access-Control-Allow-Credentials爲true
  • 注意:服務器端響應的 Access-Control-Allow-Origin 不能是通配符 *(包括options方法)
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>

    <h1>CORS</h1>
    <input type="button" onclick="XhrGetRequest();" value="put發送請求js" />
    <input type="button" onclick="JqSendRequest();" value="put發送請求jq" />

    <script type="text/javascript" src='{{static_url("jquery-2.1.1.min.js")}}'></script>
    <script type="text/javascript">
        function XhrGetRequest(){
            var xhr =new XMLHttpRequest();
            xhr.onreadystatechange = function(){
                if(xhr.readyState == 4){
                    var data = xhr.responseText;
                    alert(data);
                }
            };
            xhr.withCredentials = true;//容許跨域發送cookies
            xhr.open('put', "http://tkq2.com:8000/cors", true);

            xhr.send();
        }

        function JqSendRequest(){
            $.ajax({
                url: "http://tkq2.com:8000/cors",
                type: 'PUT',
                dataType: 'text',
                xhrFields:{withCredentials: true},//容許跨域發送cookies
                success: function(data, statusText, xmlHttpRequest){
                    alert(data);

                }
            })
        }
    </script>

</body>
</html>
HTML+JS

 

class CORSHandler(tornado.web.RequestHandler):
    # 複雜請求方法put
    def put(self):
        self.set_header('Access-Control-Allow-Origin', "http://tkq1.com:8000")
        # 設置容許跨域傳輸cookie self.set_header('Access-Control-Allow-Credentials','true')
        self.set_cookie('myck', 'c_value')
        self.write('put success')
    # 預檢方法設置
    def options(self, *args, **kwargs):
        self.set_header('Access-Control-Allow-Origin', "http://tkq1.com:8000")
        self.set_header('Access-Control-Allow-Methods', "PUT,DELETE")
        self.set_header('Access-Control-Max-Age', 10)
        #設置容許跨域傳輸cookie self.set_header('Access-Control-Allow-Credentials', 'true')
相關文章
相關標籤/搜索