最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

淺談Koa2框架利用CORS完成跨域ajax請求

 更新時間:2018年03月06日 08:37:07   作者:黃天浩  
這篇文章主要介紹了淺談Koa2框架利用CORS完成跨域ajax請求,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

實現(xiàn)跨域ajax請求的方式有很多,其中一個是利用CORS,而這個方法關(guān)鍵是在服務(wù)器端進(jìn)行配置。

本文僅對能夠完成正常跨域ajax響應(yīng)的,最基本的配置進(jìn)行說明(深層次的配置我也不會)。

CORS將請求分為簡單請求和非簡單請求,可以簡單的認(rèn)為,簡單請求就是沒有加上額外請求頭部的get和post請求,并且如果是post請求,請求格式不能是application/json(因為我對這一塊理解不深如果錯誤希望能有人指出錯誤并提出修改意見)。而其余的,put、post請求,Content-Type為application/json的請求,以及帶有自定義的請求頭部的請求,就為非簡單請求。

簡單請求的配置十分簡單,如果只是完成響應(yīng)就達(dá)到目的的話,僅需配置響應(yīng)頭部的Access-Control-Allow-Origin即可。

如果我們在http://localhost:3000 域名下想要訪問 http://127.0.0.1:3001 域名??梢宰鋈缦屡渲茫?/p>

app.use(async (ctx, next) => {
 ctx.set('Access-Control-Allow-Origin', 'http://localhost:3000');
 await next();
});

然后用ajax發(fā)起一個簡單請求,例如post請求,就可以輕松的得到服務(wù)器正確響應(yīng)了。

實驗代碼如下:

$.ajax({
  type: 'post',
  url: 'http://127.0.0.1:3001/async-post'
 }).done(data => {
  console.log(data);
})

服務(wù)器端代碼:

router.post('/async-post',async ctx => {
 ctx.body = {
 code: "1",
 msg: "succ"
 }
});

然后就能得到正確的響應(yīng)信息了。

這時候如果看一下請求和響應(yīng)的頭部信息,會發(fā)現(xiàn)請求頭部多了個origin(還有一個referer為發(fā)出請求的url地址),而響應(yīng)頭部多了個Access-Control-Allow-Origin。

現(xiàn)在可以發(fā)送簡單請求了,但是要想發(fā)送非簡單請求還是需要其他的配置。

當(dāng)?shù)谝淮伟l(fā)出非簡單請求的時候,實際上會發(fā)出兩個請求,第一次發(fā)出的是preflight request,這個請求的請求方法是OPTIONS,這個請求是否通過決定了這一個種類的非簡單請求是否能成功得到響應(yīng)。

為了能在服務(wù)器匹配到這個OPTIONS類型的請求,因此需要自己做一個中間件來進(jìn)行匹配,并給出響應(yīng)使得這個預(yù)檢能夠通過。

app.use(async (ctx, next) => {
 if (ctx.method === 'OPTIONS') {
 ctx.body = '';
 }
 await next();
});

這樣OPTIONS請求就能夠通過了。

如果檢查一下preflight request的請求頭部,會發(fā)現(xiàn)多了兩個請求頭。

Access-Control-Request-Method: PUT
Origin: http://localhost:3000

要通過這兩個頭部信息與服務(wù)器進(jìn)行協(xié)商,看是否符合服務(wù)器應(yīng)答條件。

很容易理解,既然請求頭多了兩個信息,響應(yīng)頭自然也應(yīng)該有兩個信息相對應(yīng),這兩個信息如下:

Access-Control-Allow-Origin: http://localhost:3000
Access-Control-Allow-Methods: PUT,DELETE,POST,GET

第一條信息和origin相同因此通過。第二條信息對應(yīng)Access-Controll-Request-Method,如果在請求的方式包含在服務(wù)器允許的響應(yīng)方式之中,因此這條也通過。兩個約束條件都滿足了,所以可以成功的發(fā)起請求。

至此為止,相當(dāng)于僅僅完成了預(yù)檢,還沒發(fā)送真正的請求呢。

真正的請求當(dāng)然也成功獲得了響應(yīng),并且響應(yīng)頭如下(省略不重要部分)

Access-Control-Allow-Origin: http://localhost:3000
Access-Control-Allow-Methods: PUT,DELETE,POST,GET

請求頭如下:

Origin: http://localhost:3000

這就很顯而易見了,響應(yīng)頭部信息是我們在服務(wù)器設(shè)定的,因此是這樣。

而客戶端因為剛才已經(jīng)預(yù)檢過了,所以不需要再發(fā)Access-Control-Request-Method這個請求頭了。

這個例子的代碼如下:

$.ajax({
   type: 'put',
   url: 'http://127.0.0.1:3001/put'
  }).done(data => {
   console.log(data);
});

服務(wù)器代碼:

app.use(async (ctx, next) => {
  ctx.set('Access-Control-Allow-Origin', 'http://localhost:3000');
  ctx.set('Access-Control-Allow-Methods', 'PUT,DELETE,POST,GET');
  await next();
});

至此我們完成了能夠正確進(jìn)行跨域ajax響應(yīng)的基本配置,還有一些可以進(jìn)一步配置的東西。

比如,到目前為止,每一次非簡單請求都會實際上發(fā)出兩次請求,一次預(yù)檢一次真正請求,這就比較損失性能了。為了能不發(fā)預(yù)檢請求,可以對如下響應(yīng)頭進(jìn)行配置。

Access-Control-Max-Age: 86400

這個響應(yīng)頭的意義在于,設(shè)置一個相對時間,在該非簡單請求在服務(wù)器端通過檢驗的那一刻起,當(dāng)流逝的時間的毫秒數(shù)不足Access-Control-Max-Age時,就不需要再進(jìn)行預(yù)檢,可以直接發(fā)送一次請求。

當(dāng)然,簡單請求時沒有預(yù)檢的,因此這條代碼對簡單請求沒有意義。

目前代碼如下:

app.use(async (ctx, next) => {
 ctx.set('Access-Control-Allow-Origin', 'http://localhost:3000');
 ctx.set('Access-Control-Allow-Methods', 'PUT,DELETE,POST,GET');
 ctx.set('Access-Control-Max-Age', 3600 * 24);
 await next();
});

到現(xiàn)在為止,可以對跨域ajax請求進(jìn)行響應(yīng)了,但是該域下的cookie不會被攜帶在請求頭中。如果想要帶著cookie到服務(wù)器,并且允許服務(wù)器對cookie進(jìn)一步設(shè)置,還需要進(jìn)行進(jìn)一步的配置。

為了便于后續(xù)的檢測,我們預(yù)先在http://127.0.0.1:3001這個域名下設(shè)置兩個cookie。注意不要錯誤把cookie設(shè)置成中文(剛才我就設(shè)置成了中文,結(jié)果報錯,半天沒找到出錯原因)

然后我們要做兩步,第一步設(shè)置響應(yīng)頭Access-Control-Allow-Credentials為true,然后在客戶端設(shè)置xhr對象的withCredentials屬性為true。

客戶端代碼如下:

$.ajax({
   type: 'put',
   url: 'http://127.0.0.1:3001/put',
   data: {
    name: '黃天浩',
    age: 20
   },
   xhrFields: {
    withCredentials: true
   }
  }).done(data => {
   console.log(data);
  });

服務(wù)端如下:

app.use(async (ctx, next) => {
  ctx.set('Access-Control-Allow-Origin', 'http://localhost:3000');
  ctx.set('Access-Control-Allow-Methods', 'PUT,DELETE,POST,GET');
  ctx.set('Access-Control-Allow-Credentials', true);
  await next();
});

這時就可以帶著cookie到服務(wù)器了,并且服務(wù)器也可以對cookie進(jìn)行改動。但是cookie仍是http://127.0.0.1:3001域名下的cookie,無論怎么操作都在該域名下,無法訪問其他域名下的cookie。

現(xiàn)在為止CORS的基本功能已經(jīng)都提到過了。

一開始我不知道怎么給Access-Control-Allow-Origin,后來經(jīng)人提醒,發(fā)現(xiàn)可以寫一個白名單數(shù)組,然后每次接到請求時判斷origin是否在白名單數(shù)組中,然后動態(tài)的設(shè)置Access-Control-Allow-Origin,代碼如下:

app.use(async (ctx, next) => {
 if (ctx.request.header.origin !== ctx.origin && whiteList.includes(ctx.request.header.origin)) {
  ctx.set('Access-Control-Allow-Origin', ctx.request.header.origin);
  ctx.set('Access-Control-Allow-Methods', 'PUT,DELETE,POST,GET');
  ctx.set('Access-Control-Allow-Credentials', true);
  ctx.set('Access-Control-Max-Age', 3600 * 24);
 }
 await next();
});

這樣就可以不用*通配符也可匹配多個origin了。

注意:ctx.origin與ctx.request.header.origin不同,ctx.origin是本服務(wù)器的域名,ctx.request.header.origin是發(fā)送請求的請求頭部的origin,二者不要混淆。

最后,我們再稍微調(diào)整一下自定義的中間件的結(jié)構(gòu),防止每次請求都返回Access-Control-Allow-Methods以及Access-Control-Max-Age,這兩個響應(yīng)頭其實是沒有必要每次都返回的,只是第一次有預(yù)檢的時候返回就可以了。

調(diào)整后順序如下:

app.use(async (ctx, next) => {
 if (ctx.request.header.origin !== ctx.origin && whiteList.includes(ctx.request.header.origin)) {
  ctx.set('Access-Control-Allow-Origin', ctx.request.header.origin);
  ctx.set('Access-Control-Allow-Credentials', true);
 }
 await next();
});

app.use(async (ctx, next) => {
 if (ctx.method === 'OPTIONS') {
  ctx.set('Access-Control-Allow-Methods', 'PUT,DELETE,POST,GET');
  ctx.set('Access-Control-Max-Age', 3600 * 24);
  ctx.body = '';
 }
 await next();
});

這樣就減少了多余的響應(yīng)頭。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Node.js批量給圖片加水印的方法

    Node.js批量給圖片加水印的方法

    這篇文章主要介紹了Node.js批量給圖片加水印的方法,本文分步驟給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2016-11-11
  • NodeJs的優(yōu)勢和適合開發(fā)的程序

    NodeJs的優(yōu)勢和適合開發(fā)的程序

    做頁游或webqq這樣的應(yīng)用nodejs有優(yōu)勢,但如果做微博、豆瓣、facebook這樣的社交網(wǎng)絡(luò),nodejs還有優(yōu)勢嗎?另外不知道大家是什么原因選擇的nodejs?是因為應(yīng)用需求還是對javascript這門語言的喜歡?
    2016-08-08
  • node之本地服務(wù)器圖片上傳的方法示例

    node之本地服務(wù)器圖片上傳的方法示例

    這篇文章主要介紹了node之本地服務(wù)器圖片上傳的方法示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-03-03
  • NodeJs使用webpack打包項目的方法詳解

    NodeJs使用webpack打包項目的方法詳解

    這篇文章主要為大家詳細(xì)介紹了NodeJs使用webpack打包項目的方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-02-02
  • mac安裝nvm(node.js)多版本管理實踐步驟

    mac安裝nvm(node.js)多版本管理實踐步驟

    這篇文章主要介紹了mac安裝nvm(node.js)多版本管理的相關(guān)資料,NVM是一個用于管理多個Node.js版本的命令行工具,它允許開發(fā)者在同一臺機(jī)器上安裝、切換和卸載不同版本的Node.js,從而解決版本不兼容的問題,需要的朋友可以參考下
    2025-02-02
  • nodejs 提示‘xxx’ 不是內(nèi)部或外部命令解決方法

    nodejs 提示‘xxx’ 不是內(nèi)部或外部命令解決方法

    本文介紹了node.js包管理工具npm安裝模塊后,無法通過命令行執(zhí)行命令,提示‘xxx’ 不是內(nèi)部或外部命令的解決方法,給需要的小伙伴參考下。
    2014-11-11
  • 安裝多版本node的完整步驟記錄

    安裝多版本node的完整步驟記錄

    在平時的使用中常會遇到這樣的場景,手上有多個前端項目,每個項目使用的Nodejs的版本都不太一致,下面這篇文章主要給大家介紹了關(guān)于安裝多版本node的完整步驟,需要的朋友可以參考下
    2024-01-01
  • NodeJS測試框架mocha入門教程

    NodeJS測試框架mocha入門教程

    本文給大家簡單介紹了NodeJS里最常用的測試框架--mocha的安裝以及簡單的使用方法,支持直接在browser上跑Javascript代碼測試,這里推薦給大家
    2017-03-03
  • Node搭建https服務(wù)器實例詳解

    Node搭建https服務(wù)器實例詳解

    這篇文章主要介紹了Node搭建https服務(wù)器的方法,結(jié)合實例形式詳細(xì)分析了創(chuàng)建ssl證書以及node.js調(diào)用https模塊搭建https服務(wù)器的相關(guān)操作技巧,需要的朋友可以參考下
    2023-04-04
  • Node.js Windows Binary二進(jìn)制文件安裝方法

    Node.js Windows Binary二進(jìn)制文件安裝方法

    這篇文章主要介紹了Node.js Windows Binary二進(jìn)制文件安裝,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價值 ,需要的朋友可以參考下
    2019-05-05

最新評論

祥云县| 诸城市| 达拉特旗| 桓仁| 简阳市| 光泽县| 长垣县| 托克逊县| 玉树县| 无锡市| 准格尔旗| 台南县| 贵南县| 望都县| 惠水县| 沾化县| 成武县| 唐山市| 桑植县| 正阳县| 岳西县| 娱乐| 玉龙| 胶州市| 邢台市| 湘阴县| 内黄县| 饶河县| 娄底市| 漯河市| 乌拉特中旗| 奉新县| 成都市| 海淀区| 绍兴县| 盐源县| 乌鲁木齐县| 项城市| 青神县| 阿拉尔市| 平南县|