首页 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解决跨域问题。什么是跨域请求?在Web应用程序中,跨域请求是指从一个域名的网页向另一

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

一、实现WebMvcConfigurer接口@ConfigurationpublicclassWebConfigimplementsWebMvcConfigurer{/***添加跨域支持*/@OverridepublicvoidaddCorsMappings(CorsRegistryregistry){//允许跨域访问的路径'/**'表示应用的所有方法registry.addMapping("/**")//允许跨域访问的来源'*

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

绝区零找回遗失在空洞中的宝箱怎么完成呢?这个副本里的箱子很多,但是因为散落在各处,很多人都找不到,下面我们就和你们一起分享一下如何快速找到箱子通关副本。绝区零找回遗失在空洞中的宝箱怎么完成在绳网中看到委托贴子;具体分析:1、我们可以先去绳网中看到委托贴子【找回遗失在空洞中的宝箱】,然后选择发送信息。2、交流兑换以后就可以去领取这个委托任务了,然后就可以开启这个做法了。3、然后需要我们进入空洞就可以解锁这个任务了呢。4、然后我们就可以接取盗洞客的委托,还可以得到很多数量的齿轮硬币。5、出空洞当中需

为什么我的Go程序无法正确使用CORS中间件? 为什么我的Go程序无法正确使用CORS中间件? Jun 10, 2023 pm 01:54 PM

在当今互联网应用程序中,跨域资源共享(CORS)是一种常用的技术,它允许网站从不同的域访问资源。在开发过程中,我们常常会遇到一些问题,特别是在使用CORS中间件时。本文将探究为什么您的Go程序无法正确使用CORS中间件,并提供针对这些问题的解决方案。确认是否已启用CORS中间件首先,确保已在您的Go程序中启用了CORS中间件。如果没有启用,那么您的程序将无法

安全帽的万能绝区如何实现 安全帽的万能绝区如何实现 Jan 24, 2024 pm 02:36 PM

绝区零万能的安全帽怎么完成呢?要做这个任务,必须要接取一个先行任务,其实就是去到黑燕工地的旧址,然后接取任务,但是到底要怎么做才能完成?下面就和小编一起看看吧。绝区零万能的安全帽怎么完成1、前往黑雁工地旧址的位置处,需要在i这里找到铁头然后就是与他进行对话。2、进行对话之后需要前往坑中的水泥袋旁边,之后就能够在这里看到三个负责安全帽的人,在这里借安全帽。3、之后需要找到谨慎的工人进行对话,对话完成后返回寻找铁头。4、最后与铁头进行对话就能够完成任务了。上述信息就是有关于绝区零万能的安全帽怎么完成

See all articles