首頁 web前端 js教程 怎樣用Koa2框架的CORS完成跨域ajax請求

怎樣用Koa2框架的CORS完成跨域ajax請求

Mar 28, 2018 am 11:50 AM
cors koa2 完成

這次帶給大家怎樣用Koa2框架的CORS完成跨域ajax請求,用Koa2框架的CORS完成跨域ajax請求的注意事項有哪些,下面就是實戰案例,一起來看一下。

實現跨域ajax請求的方式有很多,其中一個是利用CORS,而這個方法關鍵是在伺服器端進行設定。

本文僅對能夠完成正常跨域ajax回應的,最基本的配置進行說明(深層的配置我也不會)。

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

簡單請求的設定十分簡單,如果只是完成回應就達到目的的話,只需設定回應頭部的Access-Control-Allow-Origin即可。

如果我們在http://localhost:3000 網域下想要造訪 http://127.0.0.1:3001 網域。可以做如下設定:

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

然後用ajax發起一個簡單請求,例如post請求,就可以輕鬆的得到伺服器正確回應了。

實驗程式碼如下:

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

伺服器端程式碼:

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

然後就能得到正確的回應訊息了。

這時候如果看一下請求和回應的頭部訊息,會發現請求頭部多了個origin(還有一個referer為發出請求的url位址),而回應頭部多了個Access- Control-Allow-Origin。

現在可以發送簡單請求了,但是要想傳送非簡單請求還是需要其他的設定。

當第一次發出非簡單請求的時候,實際上會發出兩個請求,第一次發出的是preflight request,這個請求的請求方法是OPTIONS,這個請求是否透過決定了這一個種類的非簡單請求是否能成功得到回應。

為了能在伺服器匹配到這個OPTIONS類型的請求,因此需要自己做一個中間件來進行匹配,並給出回應使得這個預檢能夠通過。

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

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

如果檢查一下preflight request的請求頭部,會發現多了兩個請求頭。

Access-Control-Request-Method: PUT
Origin: http://localhost:3000
登入後複製

要透過這兩個頭部資訊與伺服器進行協商,看是否符合伺服器應答條件。

很容易理解,既然請求頭多了兩個訊息,回應頭自然也應該有兩個訊息相對應,這兩個訊息如下:

Access-Control-Allow-Origin: http://localhost:3000
Access-Control-Allow-Methods: PUT,DELETE,POST,GET
登入後複製
登入後複製

第一個訊息和origin相同因此通過。第二個訊息對應Access-Controll-Request-Method,如果在請求的方式包含在伺服器允許的回應方式之中,因此這條也通過。兩個約束條件都滿足了,所以可以成功的發起請求。

至此為止,相當於僅僅完成了預檢,還沒發送真正的請求。

真正的請求當然也成功獲得了回應,並且回應頭如下(省略不重要部分)

Access-Control-Allow-Origin: http://localhost:3000
Access-Control-Allow-Methods: PUT,DELETE,POST,GET
登入後複製
登入後複製

請求頭如下:

Origin: http://localhost:3000
登入後複製

這就很顯而易見了,回應頭部資訊是我們在伺服器設定的,因此是這樣。

而客戶端因為剛才已經預先檢查過了,所以不需要再發Access-Control-Request-Method這個請求頭了。

這個範例的程式碼如下:

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

伺服器程式碼:

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();
});
登入後複製

至此我們完成了能夠正確進行跨網域ajax回應的基本配置,還有一些可以進一步配置的東西。

例如,到目前為止,每一次非簡單請求都會實際上發出兩次請求,一次預檢一次真正請求,這就比較損失性能了。為了能不發預檢請求,可以設定如下回應頭。

Access-Control-Max-Age: 86400
登入後複製

这个响应头的意义在于,设置一个相对时间,在该非简单请求在服务器端通过检验的那一刻起,当流逝的时间的毫秒数不足Access-Control-Max-Age时,就不需要再进行预检,可以直接发送一次请求。

当然,简单请求时没有预检的,因此这条代码对简单请求没有意义。

目前代码如下:

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();
});
登入後複製

到现在为止,可以对跨域ajax请求进行响应了,但是该域下的cookie不会被携带在请求头中。如果想要带着cookie到服务器,并且允许服务器对cookie进一步设置,还需要进行进一步的配置。

为了便于后续的检测,我们预先在http://127.0.0.1:3001这个域名下设置两个cookie。注意不要错误把cookie设置成中文(刚才我就设置成了中文,结果报错,半天没找到出错原因)

然后我们要做两步,第一步设置响应头Access-Control-Allow-Credentials为true,然后在客户端设置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);
  });
登入後複製

服务端如下:

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到服务器了,并且服务器也可以对cookie进行改动。但是cookie仍是http://127.0.0.1:3001域名下的cookie,无论怎么操作都在该域名下,无法访问其他域名下的cookie。

现在为止CORS的基本功能已经都提到过了。

一开始我不知道怎么给Access-Control-Allow-Origin,后来经人提醒,发现可以写一个白名单数组,然后每次接到请求时判断origin是否在白名单数组中,然后动态的设置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是本服务器的域名,ctx.request.header.origin是发送请求的请求头部的origin,二者不要混淆。

最后,我们再稍微调整一下自定义的中间件的结构,防止每次请求都返回Access-Control-Allow-Methods以及Access-Control-Max-Age,这两个响应头其实是没有必要每次都返回的,只是第一次有预检的时候返回就可以了。

调整后顺序如下:

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();
});
登入後複製

这样就减少了多余的响应头。

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

在Vue2.0中http请求以及loading的展示

process和child_process使用详解

以上是怎樣用Koa2框架的CORS完成跨域ajax請求的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

如何使用Flask-CORS實現跨域資源共享 如何使用Flask-CORS實現跨域資源共享 Aug 02, 2023 pm 02:03 PM

如何使用Flask-CORS實現跨域資源共享引言:在網路應用開發中,跨域資源共享(CrossOriginResourceSharing,簡稱CORS)是一種機制,允許伺服器與指定的來源或網域名稱之間共享資源。使用CORS,我們可以靈活地控制不同域之間的資料傳輸,實現安全、可靠的跨域存取。在本文中,我們將介紹如何使用Flask-CORS擴充庫來實現CORS功

如何在PHP-Slim框架中使用CORS跨域請求? 如何在PHP-Slim框架中使用CORS跨域請求? Jun 03, 2023 am 08:10 AM

在Web開發中,跨域請求是一個常見的問題。這是因為瀏覽器對於不同網域名稱之間的請求有嚴格的限制。例如,網站A的前端程式碼無法直接向網站B的API發送請求,除非網站B允許跨網域請求。為了解決這個問題,出現了CORS(跨域資源共享)技術。本文將介紹如何在PHP-Slim框架中使用CORS跨域請求。一、什麼是CORSCORS是一種機制,它透過在對應的HTTP頭中添加一些額

如何使用 Golang 建立 RESTful API 並實作 CORS? 如何使用 Golang 建立 RESTful API 並實作 CORS? Jun 02, 2024 pm 05:52 PM

建立RESTfulAPI並實作CORS:建立專案並安裝相依性。設定HTTP路由處理請求。使用middlewareCORS中間件啟用跨域資源共享(CORS)。將CORS中間件套用至路由器,允許來自任何網域的GET和OPTIONS請求。

在Beego框架中使用CORS解決跨域問題 在Beego框架中使用CORS解決跨域問題 Jun 04, 2023 pm 07:40 PM

隨著Web應用程式的發展和互聯網的全球化,越來越多的應用程式需要進行跨域請求。對於前端開發人員而言,跨域請求是一個常見的問題,它可能導致應用程式無法正常運作。在這種情況下,解決跨域請求問題的最佳方法之一是使用CORS。在本文中,我們將重點放在如何在Beego框架中使用CORS來解決跨域問題。什麼是跨域請求?在網路應用程式中,跨網域請求是指從一個網域的網頁向另一

springboot解決CORS跨域的方式有哪些 springboot解決CORS跨域的方式有哪些 May 13, 2023 pm 04:55 PM

一、實作WebMvcConfigurer介面@ConfigurationpublicclassWebConfigimplementsWebMvcConfigurer{/***新增跨網域支援*/@OverridepublicvoidaddCorsMappings(CorsRegistryregistry){//允許跨網域存取的路徑'/**'表示應用程式的所有方法? ")//允許跨網域存取的來源'*

如何在空洞中找回遺失的寶箱 如何在空洞中找回遺失的寶箱 Jan 22, 2024 pm 05:30 PM

絕區零找回遺失在空洞中的寶箱怎麼完成呢?這個副本裡的箱子很多,但是因為散落在各處,很多人都找不到,下面我們就和你們一起分享如何快速找到箱子通關副本。絕區零找回遺失在空洞中的寶箱怎麼完成在繩網中看到委託貼子;具體分析:1、我們可以先去繩網中看到委託貼圖【找回遺失在空洞中的寶箱】 ,然後選擇發送訊息。 2.交流兌換以後就可以去領取這個委託任務了,然後就可以開啟這個做法了。 3、然後需要我們進入空洞就可以解鎖這個任務了呢。 4.然後我們就可以接取盜洞客的委託,還可以得到很多數量的齒輪硬幣。 5.出空洞當中需

安全帽的萬能絕區如何實現 安全帽的萬能絕區如何實現 Jan 24, 2024 pm 02:36 PM

絕區零萬用的安全帽要怎麼完成?要做這個任務,必須接取一個先行任務,其實就是去到黑燕工地的舊址,然後接取任務,但是到底要怎麼做才能完成?下面就跟小編一起看看吧。絕區零萬能的安全帽怎麼完成1、前往黑雁工地舊址的位置處,需要在i這裡找到鐵頭然後就是與他進行對話。 2.進行對話之後需要前往坑中的水泥袋旁邊,之後就能夠在這裡看到三個負責安全帽的人,在這裡借安全帽。 3.之後需要找到謹慎的工人進行對話,對話完成後再回到尋找鐵頭。 4.最後與鐵頭對話就能夠完成任務了。上述資訊就是有關於絕區零萬能的安全帽怎麼完成

為什麼我的Go程式無法正確使用CORS中間件? 為什麼我的Go程式無法正確使用CORS中間件? Jun 10, 2023 pm 01:54 PM

在當今互聯網應用程式中,跨域資源共享(CORS)是一種常用的技術,它允許網站從不同的網域存取資源。在開發過程中,我們常常會遇到一些問題,特別是在使用CORS中間件時。本文將探討為什麼您的Go程式無法正確使用CORS中介軟體,並提供這些問題的解決方案。確認是否已啟用CORS中間件首先,請確保已在您的Go程序中啟用了CORS中間件。如果沒有啟用,那麼您的程式將無法

See all articles