使用 actix-web 时缺少“Access-Control-Allow-Origin”

Muh*_*jid 5 http rust rust-actix actix-web

陷入这个问题,每次向我的 actix-web 服务器发出 POST 请求时都会收到此错误。

CORS header 'Access-Control-Allow-Origin' missing
Run Code Online (Sandbox Code Playgroud)

我的 javascript (VueJs 在 localhost:3000 上运行):

let data = //some json data
let xhr = new XMLHttpRequest();
xhr.open("POST", "http://localhost:8080/abc");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.onload = () => {
    console.log(xhr.responseText);
}
xhr.send(JSON.stringify(data));
Run Code Online (Sandbox Code Playgroud)

我的 Actix_Web 服务器(在 localhost:8080 上运行):

#[actix_web::main]
async fn main() {

    HttpServer::new(move || {
        let cors = Cors::default()
        .allowed_origin("http://localhost:3000/")
        .allowed_methods(vec!["GET", "POST"])
        .allowed_header(actix_web::http::header::ACCEPT)
        .allowed_header(actix_web::http::header::CONTENT_TYPE)
        .max_age(3600);

        App::new()
        .wrap(cors)
        .service(myfunc)
    })
    .bind(("0.0.0.0", 8080))
    .unwrap()
    .run()
    .await
    .unwrap();

}
Run Code Online (Sandbox Code Playgroud)

我的 Cargo.toml 依赖项

[dependencies]
actix-web = "4"
actix-cors = "0.6.1"
...

Run Code Online (Sandbox Code Playgroud)

有什么想法吗?

Eli*_*ias 5

好的,我做了一些测试。如果您正在编写公共 API,您可能希望允许所有来源。为此,您可以使用以下代码:

HttpServer::new(|| {
    let cors = Cors::default().allow_any_origin().send_wildcard();

    App::new().wrap(cors).service(greet)
})
Run Code Online (Sandbox Code Playgroud)

如果您不编写公共 API...那么,我不确定他们希望您做什么。我还没弄清楚如何告诉库发送该标头。我想我会看看代码。

更新:

如此有趣的故事,这就是您允许特定起源的方式:

let cors = Cors::default()
    .allowed_origin("localhost:3000")
    .allowed_origin("localhost:2020");
Run Code Online (Sandbox Code Playgroud)

但是,天哪,那真是多汁啊。Access-Control-Allow-Origin仅当存在Origin 请求标头时才设置响应标头。在某些情况下,该标头通常由浏览器添加1。所以我这样做了(使用浏览器中的开发人员工具)。我得到了什么?"Origin is not allowed to make this request"。我将原始标头设置为localhost:3000. 事实证明,如果没有提供协议,arctix 库就会简单地丢弃该标头...(例如http://)(我假设它会丢弃它,如果它认为其格式无效)。这在内部导致 header 成为string "null"。也就是说,检查注释,不在允许的来源列表中。

现在是大结局:

  1. 您的原始标头需要设置为(由您或浏览器设置):"http://localhost:3000"
  2. 您的配置需要包括:.allowed_origin("http://localhost:3000").

完成此操作后,服务器会很乐意origin在标头中回显您的标头Access-Control-Allow-Origin。而且它只会发送那个

我不知道其中是否有标准指定(或没有)。我鼓励您仔细阅读它,如果不符合要求,请在 GitHub 上提出问题。我会自己做,但今天我已经完成了编程。

干杯!