摘要:注意,該請求的查詢字符串有一個參數(shù),用來指定回調(diào)函數(shù)的名字,這對于是必需的。服務器收到這個請求以后,會將數(shù)據(jù)放在回調(diào)函數(shù)的參數(shù)位置返回。
有關(guān)同源策略詳細介紹,請看這里JSONP
JSONP是服務器與客戶端跨源通信的常用方法。最大特點就是簡單適用,老式瀏覽器全部支持,服務器改造非常小。
它的基本思想是,網(wǎng)頁通過添加一個元素,向服務器請求JSON數(shù)據(jù),這種做法不受同源政策限制;服務器收到請求后,將數(shù)據(jù)放在一個指定名字的回調(diào)函數(shù)里傳回來。
首先,網(wǎng)頁動態(tài)插入元素,由它向跨源網(wǎng)址發(fā)出請求。
例子:
客服端
function addScriptTag(src) { var script = document.createElement("script"); script.setAttribute("type","text/javascript"); script.src = src; document.body.appendChild(script); } window.onload = function () { addScriptTag("http://localhost:3000/test?callback=foo"); } function foo(data) { console.log("Your public IP address is: " + data.ip); };
上面代碼通過動態(tài)添加元素,向服務器http://localhost:3000發(fā)出請求。注意,該請求的查詢字符串有一個callback參數(shù),用來指定回調(diào)函數(shù)的名字,這對于JSONP是必需的。
服務器收到這個請求以后,會將數(shù)據(jù)放在回調(diào)函數(shù)的參數(shù)位置返回。
JavaScript服務端
var express = require("express"); var app = express(); app.get("/test", function (req, res) { var cbFunction = req.query.callback res.send(`${cbFunction}({"ip":"110.110.110.110"})`); //或者不用那么麻煩直接通過express提供的API /** * res.jsonp({ip:"110.110.110.110"}); */ }); var server = app.listen(3000, function () { var host = server.address().address; var port = server.address().port; console.log("Example app listening at http://%s:%s", host, port); });
上面代碼通過express做的簡單后臺,當請求接口時,后端拿到callback參數(shù)然后將其與要返回的數(shù)據(jù)組合成字符串的形式返回給客戶端。
由于元素請求的腳本,直接作為代碼運行。這時,只要瀏覽器定義了foo函數(shù),該函數(shù)就會立即調(diào)用。作為參數(shù)的JSON數(shù)據(jù)被視為JavaScript對象,而不是字符串,因此避免了使用JSON.parse的步驟。
CORS有兩種請求 :簡單請求(simple request)和非簡單請求(not-so-simple request)只要同時滿足以下兩大條件,就屬于簡單請求。
請求方法是以下三種方法之一:
HEAD
GET
POST
HTTP的頭信息不超出以下幾種字段:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:只限于三個值application/x-www-form-urlencoded、multipart/form-data、text/plain
凡是不同時滿足上面兩個條件,就屬于非簡單請求。
瀏覽器對這兩種請求的處理,是不一樣的。
客戶端
var xhr = new XMLHttpRequest() xhr.open("post","http://localhost:3000/test",true) xhr.onload = function(e){ if(e.currentTarget.status==200){ alert(e.currentTarget.responseText) } } xhr.send()
RequestHeaders請求頭信息
Accept:/*/ Accept-Encoding:gzip, deflate, br Accept-Language:zh-CN,zh;q=0.8 Connection:keep-alive Content-Length:0 Host:localhost:3000 Origin:http://localhost:8020 Referer:http://localhost:8020/ User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36
JavaScript服務端
app.post("/test", function (req, res) { res.set("Access-Control-Allow-Origin","http://localhost:8020") res.send({ name:"tom" }) });
ResponseHeaders
Access-Control-Allow-Origin:http://localhost:8020 Connection:keep-alive Content-Length:14 Content-Type:application/json; charset=utf-8 Date:Mon, 09 Apr 2018 02:09:05 GMT ETag:W/"e-v50e5W1R/vD6VVQyxqDA0eSWedA" X-Powered-By:Express非簡單請求 預檢請求
客戶端
var xhr = new XMLHttpRequest() xhr.open("put","http://localhost:3000/test",true) xhr.setRequestHeader("X-Custom-Header", "value"); xhr.onload = function(e){ if(e.currentTarget.status==200){ alert(e.currentTarget.responseText) } } xhr.send()
當發(fā)送上面的http請求時瀏覽器會先發(fā)送一個options類型的http的預檢請求
RequestHeaders請求頭信息
Accept:*/* Accept-Encoding:gzip, deflate, br Accept-Language:zh-CN,zh;q=0.8 Access-Control-Request-Headers:x-custom-header Access-Control-Request-Method:PUT Connection:keep-alive Host:localhost:3000 Origin:http://localhost:8020 Referer:http://localhost:8020/ User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36
JavaScript服務端
//options類型用于CORS非簡單請求的預檢請求 app.options("/test",function(req,res){ res.set("Access-Control-Allow-Origin","http://localhost:8020") //必須設置 res.set("Access-Control-Allow-Methods","PUT") //必須設置 res.set("Access-Control-Allow-Headers","X-Custom-Header") //如果瀏覽器請求包括Access-Control-Request-Headers字段,則Access-Control-Allow-Headers字段是必需的。 res.send({status:200,msg:"預檢成功!"}) })
ResponseHeaders
Access-Control-Allow-Headers:X-Custom-Header Access-Control-Allow-Methods:PUT Access-Control-Allow-Origin:http://localhost:8020 Connection:keep-alive Content-Length:38 Content-Type:application/json; charset=utf-8 Date:Mon, 09 Apr 2018 04:08:40 GMT ETag:W/"26-+1THtR73k4ca8avMcdsJULlJZUs" X-Powered-By:Express
關(guān)于客戶端和服務端字段相應說明可以在這里查看正常請求和回應
一旦服務器通過了"預檢"請求,以后每次瀏覽器正常的CORS請求,就都跟簡單請求一樣,會有一個Origin頭信息字段。服務器的回應,也都會有一個Access-Control-Allow-Origin頭信息字段。
客戶端
RequestHeaders請求頭信息
Accept:*/* Accept-Encoding:gzip, deflate, br Accept-Language:zh-CN,zh;q=0.8 Connection:keep-alive Content-Length:0 Host:localhost:3000 Origin:http://localhost:8020 Referer:http://localhost:8020/ User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36 X-Custom-Header:value
上面頭信息的Origin字段是瀏覽器自動添加的。
JavaScript服務端
app.put("/test", function (req, res) { res.set("Access-Control-Allow-Origin","http://localhost:8020") res.send({ name:"tom" }) });
ResponseHeaders
Access-Control-Allow-Origin:http://localhost:8020 Connection:keep-alive Content-Length:14 Content-Type:application/json; charset=utf-8 Date:Mon, 09 Apr 2018 04:08:40 GMT ETag:W/"e-v50e5W1R/vD6VVQyxqDA0eSWedA" X-Powered-By:Express
上面頭信息中,Access-Control-Allow-Origin字段是每次回應都必定包含的。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/94208.html
摘要:關(guān)于,強烈推薦閱讀跨域資源共享詳解阮一峰另外,這里也整理了一個實現(xiàn)原理圖簡化版如何判斷是否是簡單請求瀏覽器將請求分成兩類簡單請求和非簡單請求。 前言 從剛接觸前端開發(fā)起,跨域這個詞就一直以很高的頻率在身邊重復出現(xiàn),一直到現(xiàn)在,已經(jīng)調(diào)試過N個跨域相關(guān)的問題了,16年時也整理過一篇相關(guān)文章,但是感覺還是差了點什么,于是現(xiàn)在重新梳理了一下。 個人見識有限,如有差錯,請多多見諒,歡迎提出iss...
摘要:本地也可以輕松模擬跨域請求,以及解決跨域請求的方式輕松實現(xiàn)本地服務器跨域請求請求接口,其實它們都在相同的本地服務器目錄下以訪問頁面,可是這個頁面調(diào)用的接口地址是與域名不同,也即跨域解決跨域請求服務器端設置這樣就能輕松實現(xiàn)跨域請求 本地也可以輕松模擬跨域請求,以及解決跨域請求的方式 1、輕松實現(xiàn)本地服務器跨域請求 web.html請求接口json.json,其實它們都在相同的本地服務器目...
摘要:前言由于自己平時只做做,并沒有遇到太多跨域問題,今天通過幾個樣例模擬實現(xiàn)了幾種跨域方式。 前言 由于自己平時只做做demo,并沒有遇到太多跨域問題,今天通過幾個樣例模擬實現(xiàn)了幾種跨域方式。原文地址 傳送門 本文所有樣例靜態(tài)服務器基于nodejs實現(xiàn),代碼親測可用。測試步驟如下: 1.為了實現(xiàn)跨域訪問的效果,需要下載http-server 作為一個服務器 npm install http...
摘要:二跨域解決方案原理利用標簽沒有跨域限制的漏洞,網(wǎng)頁可以得到從其他來源動態(tài)產(chǎn)生的數(shù)據(jù)。使用反向代理實現(xiàn)跨域,是最簡單的跨域方式。 前言 前后端數(shù)據(jù)交互經(jīng)常會碰到請求跨域,什么是跨域,以及有哪幾種跨域方式,這是本文要探討的內(nèi)容。 本文完整的源代碼請猛戳github博客,紙上得來終覺淺,建議動手敲敲代碼 一、什么是跨域? 1.什么是同源策略及其限制內(nèi)容? 同源策略是一種約定,它是瀏覽器最核心...
摘要:二跨域解決方案原理利用標簽沒有跨域限制的漏洞,網(wǎng)頁可以得到從其他來源動態(tài)產(chǎn)生的數(shù)據(jù)。使用反向代理實現(xiàn)跨域,是最簡單的跨域方式。 前言 前后端數(shù)據(jù)交互經(jīng)常會碰到請求跨域,什么是跨域,以及有哪幾種跨域方式,這是本文要探討的內(nèi)容。 本文完整的源代碼請猛戳github博客,紙上得來終覺淺,建議動手敲敲代碼 一、什么是跨域? 1.什么是同源策略及其限制內(nèi)容? 同源策略是一種約定,它是瀏覽器最核心...
閱讀 2928·2021-11-04 16:06
閱讀 767·2021-09-30 09:56
閱讀 1832·2021-09-22 10:02
閱讀 2612·2019-08-29 13:43
閱讀 2198·2019-08-29 13:42
閱讀 2288·2019-08-29 12:21
閱讀 1038·2019-08-29 11:29
閱讀 1377·2019-08-26 13:51