【问题标题】:Access-control-allow-headers isn't allowed不允许访问控制允许标头
【发布时间】:2019-07-09 00:05:46
【问题描述】:

所以我有一个小角度应用程序连接到我的节点 api。我的获取请求没有问题,我在加载时从我的 api 获取数据。我的发布请求引发了错误;

从源“http://localhost:4200”对“http://localhost:3000/api/heroes”处的 XMLHttpRequest 的访问已被 CORS 策略阻止:在预检响应中 Access-Control-Allow-Headers 不允许请求标头字段内容类型。

ERROR HttpErrorResponse {headers: HttpHeaders, status: 0, statusText: "Unknown Error", url: "http://localhost:3000/api/heroes", ok: false, ...}

这是我的post方法@客户端;

addHero(hero: Hero) { 
    this.http.post<Hero>("http://localhost:3000/api/heroes", hero)
        .subscribe((responseData) => {
            console.log(responseData);
        })
    this.heroes.push(hero); //Adds new hero to original array
    this.heroesUpdated.next([...this.heroes]); //Adds new array to subject
}

这是我的后端;

app.use((req,res,next) => {
res.setHeader("Access-Control-Allow-Origin", "localhost"); 
res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); 
res.setHeader("Access-Control-Allow-Methods","GET, POST, PATCH, DELETE, OPTIONS");
next();
})

app.post("/api/heroes", (req, res,next) => {
const post = req.body;
console.log(post);
res.status(201).json({message:"Succeed"});
});

所以我已经允许 content-type 但我仍然收到错误。有什么建议可以从这里继续吗?

【问题讨论】:

    标签: node.js angular cors http-headers


    【解决方案1】:

    您正确理解问题在于 CORS。

    您的错误是:预检响应中的 Access-Control-Allow-Headers 不允许请求标头字段内容类型。

    在某些情况下,客户端会向服务器发送“预检请求”。什么时候?

    例如,当您的内容类型为“复杂”时。复杂意味着不在application/x-www-form-urlencodedmultipart/form-datatext/plain 中。

    或者当您发送带有正文的 POST 请求时。

    还有其他场合,你可以阅读更多关于这个on MDN的内容。

    预检请求只是一个带有“OPTIONS”方法的请求,它到达同一个端点。它期望收到一个

    1. 成功响应

    2. 允许所有标题

    3. 并允许原点。

    您的 express 中间件 app.use((req,res,next) =&gt; {... 符合要求 2 和 3。(实际上对于 3,我建议将“Access-Control-Allow-Origin”标头设置为 http://localhost:4200 而不仅仅是 localhost

    但是您没有中间件或路由处理程序来处理 OPTIONS 请求。让我们添加一个:

    如果我们收到一个 OPTIONS 请求,我们会返回 200 OK。 如果不是 OPTIONS 请求,则转到下一个处理程序。

    app.use((req, res) => {
        if (req.method === 'OPTIONS') {
            return res.sendStatus(200);
        }
        next();
    });
    

    由于我们希望对 ALSO 的 OPTIONS 响应设置正确的标头,因此我们必须将其包含在 “cors 中间件”之后:

    app.use((req,res,next) => {
    // set cors headers and call next()
    });
    
    app.use((req, res, next) => {
    // handle preflight requests
    });
    
    app.post('api/heroes', ...)
    

    最后,当然有现成的解决方案,例如 npm 上的 cors 包,它为 express 提供中间件。在其npm page 上查看如何使用它。

    【讨论】:

    • 非常感谢。接受并赞成。当您不仅被告知要做什么,而是被告知实际发生了什么时,这真是太神奇了。真的很辛苦