koa2 给某条特定的 url 设置 cors 后,前端 ajax 自定义头部后就无法跨域,去掉头部就能跨域

2018-06-11 23:08:19 +08:00
 deepred

app.js

const Koa = require('koa');
const Router = require('koa-router');
const router = new Router();
const app = new Koa();



router.all('*',function (ctx, next) {
    ctx.set('Access-Control-Allow-Origin', '*');
    ctx.set('Access-Control-Allow-Headers', 'Content-Type, myheader');
    ctx.set('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS');

    next();
  });


router.post('/api/test/', (ctx, next) => {
    ctx.body = {
        status: 'success'
    }
});

router.post('/api/test2/', (ctx, next) => {
    ctx.body = {
        status: 'success'
    }
});



app.use(router.routes()).use(router.allowedMethods());



app.listen(8089);


console.log('server start at 8089')

前端自定义头部myheader

axios.post(`http://localhost:8089/api/test`, null, { headers: { 'myheader': 'test' }})
        .then(response => {
            console.log(response.data);
        });

后台把所有的接口都设置成 cors,前端是可以自定义头部的。

但是如果我只是让其中一个接口 cors

const Koa = require('koa');
const Router = require('koa-router');
const router = new Router();
const app = new Koa();



router.post('/api/test/', (ctx, next) => {
    ctx.set('Access-Control-Allow-Origin', '*');
    ctx.set('Access-Control-Allow-Headers', 'Content-Type, myheader');
    ctx.set('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS');
    ctx.body = {
        status: 'success'
    }
});

router.post('/api/test2/', (ctx, next) => {
    ctx.body = {
        status: 'success'
    }
});



app.use(router.routes()).use(router.allowedMethods());



app.listen(8089);


console.log('server start at 8089')

这时前端设置自定义头部,就会报错 说没有No 'Access-Control-Allow-Origin' header,但是我已经设置过Access-Control-Allow-Headers了。

如果前端把自定义头部去掉,这时又能跨域成功

// 正常跨域
axios.post(`http://localhost:8089/api/test`)
        .then(response => {
            console.log(response.data);
        });

求解决方法

5730 次点击
所在节点    Node.js
7 条回复
Sparetire
2018-06-12 01:39:00 +08:00
因为你这里单独接口的时候没有对 option 请求做出响应
deepred
2018-06-12 08:07:04 +08:00
@Sparetire 嗯,就是这个原因
deepred
2018-06-12 08:12:36 +08:00
@Sparetire 但是为啥单独接口的时候,我不加自定义头部,虽然没对 option 做响应,但是也跨域成功了?
KuroNekoFan
2018-06-12 09:12:36 +08:00
我没看错的话你代码不是就是这个意思吗……上面的代码是 router.all ,下面是 post (“ api/test ”)
dtysky
2018-06-12 10:03:25 +08:00
详细看看跨域控制协议吧,只有 simple request 不会发预置 options 请求,而它是有限制的(比如只能报告某些头部)。
Sparetire
2018-06-12 10:40:16 +08:00
@deepred 因为这里不带自定义头部不需要 option 请求,具体参考同源策略和跨域协商的细节
wotemelon
2018-06-20 09:35:05 +08:00
router.post('/api/test/', (ctx, next) => {
ctx.set('Access-Control-Allow-Origin', '*');
ctx.set('Access-Control-Allow-Headers', 'Content-Type, myheader');
ctx.set('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS');
ctx.body = {
status: 'success'
}
});

你这里处理了`post`请求啊,你要把`post`改成`all`。在你没有单独拦截接口的时候,你用的是`all`,当然包括了`option`

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/462302

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX