抽奖小程序流程是甚么_浅谈Koa2框架使用CORS完成跨域ajax请求

浅谈Koa2框架利用CORS完成跨域ajax请求       这篇文章主要介绍了浅谈Koa2框架利用CORS完成跨域ajax请求,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

实现跨域ajax请求的方式有很多,其中一个是利用CORS,而这个方法关键是在服务器端进行配置。

本文仅对能够完成正常跨域ajax响应的,最基本的配置进行说明(深层次的配置我也不会)。

CORS将请求分为简单请求和非简单请求,可以简单的认为,简单请求就是没有加上额外请求头部的get和post请求,并且如果是post请求,请求格式不能是application/json(因为我对这一块理解不深如果错误希望能有人指出错误并提出修改意见)。而其余的,put、post请求,Content-Type为application/json的请求,以及带有自定义的请求头部的请求,就为非简单请求。

简单请求的配置十分简单,ess-Control-Allow-Origin即可。

如果我们在/127.0.0.1:3001 域名。可以做如下配置:

app.use(async (ctx, next) = {
 ctx.set('Access-Control-Allow-Origin', 'pre>

然后用ajax发起一个简单请求,例如post请求,就可以轻松的得到服务器正确响应了。

实验代码如下:

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

服务器端代码:

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

然后就能得到正确的响应信息了。

这时候如果看一下请求和响应的头部信息,会发现请求头部多了个origin(还有一个referer为发出请求的url地址),ess-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: pre>

要通过这两个头部信息与服务器进行协商,看是否符合服务器应答条件。

很容易理解,既然请求头多了两个信息,响应头自然也应该有两个信息相对应,这两个信息如下:

Access-Control-Allow-Origin: pre>

ess-Controll-Request-Method,如果在请求的方式包含在服务器允许的响应方式之中,因此这条也通过。两个约束条件都满足了,所以可以成功的发起请求。

至此为止,相当于仅仅完成了预检,还没发送真正的请求呢。

真正的请求当然也成功获得了响应,并且响应头如下(省略不重要部分)

Access-Control-Allow-Origin: pre>

请求头如下:

Origin: pre>

这就很显而易见了,响应头部信息是我们在服务器设定的,因此是这样。

ess-Control-Request-Method这个请求头了。

这个例子的代码如下:

$.ajax({
 type: 'put',
 url: 'put'
 }).done(data = {
 console.log(data);

服务器代码:

app.use(async (ctx, next) = {
 ctx.set('Access-Control-Allow-Origin', 'pre>

至此我们完成了能够正确进行跨域ajax响应的基本配置,还有一些可以进一步配置的东西。

比如,到目前为止,每一次非简单请求都会实际上发出两次请求,一次预检一次真正请求,这就比较损失性能了。为了能不发预检请求,可以对如下响应头进行配置。

Access-Control-Max-Age: 86400

这个响应头的意义在于,设置一个相对时间,ess-Control-Max-Age时,就不需要再进行预检,可以直接发送一次请求。

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

目前代码如下:

app.use(async (ctx, next) = {
 ctx.set('Access-Control-Allow-Origin', 'pre>

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

为了便于后续的检测,我们预先在p>

ess-Control-Allow-Credentials为true,然后在客户端设置xhr对象的withCredentials属性为true。

客户端代码如下:

$.ajax({
 type: 'put',
 url: 'put',
 data: {
 name: '黄天浩',
 age: 20
 xhrFields: {
 withCredentials: true
 }).done(data = {
 console.log(data);

服务端如下:

app.use(async (ctx, next) = {
 ctx.set('Access-Control-Allow-Origin', 'pre>

这时就可以带着cookie到服务器了,并且服务器也可以对cookie进行改动。但是cookie仍是p>

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

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,二者不要混淆。

最后,ess-Control-ess-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();

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持凡科。


相关阅读