很容易理解,既然请求头多了两个信息,响应头自然也应该有两个信息相对应,这两个信息如下:
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进一步设置,还需要进行进一步的配置。









