如何为 Rocket.rs 设置 CORS 或 OPTIONS

Wil*_*ill 3 http rust dart rust-rocket flutter-web

我有一个运行 Rocket.rs 的后端,我的 Flutter Web 应用程序向它发送请求,但它无法通过 OPTIONS 响应。

我曾尝试将 CORS (rocket_cors) 添加到后端并有一个选项响应,但它仍然发回:

Error: XMLHttpRequest error.
    dart:sdk_internal 124039:30                           get current
packages/http/src/browser_client.dart.lib.js 214:124  <fn>
Run Code Online (Sandbox Code Playgroud)

我在我的火箭项目中添加了以下内容:

Error: XMLHttpRequest error.
    dart:sdk_internal 124039:30                           get current
packages/http/src/browser_client.dart.lib.js 214:124  <fn>
Run Code Online (Sandbox Code Playgroud)

我的颤振应用程序正在运行此请求:

Future<String> fetchData() async {
  final data2 = await http.get("http://my-web-site.com").then((response) { // doesn't get past here
    return response.body; 
  });
  return data2;
}
Run Code Online (Sandbox Code Playgroud)

问题:这是响应 OPTION 请求的正确方法,如果不是,我如何在 Rocket.rs 中实现它?

mig*_*hen 15

这对我来说适用于 Rocket 0.5.0-rc.2,没有其他依赖项。它基于上面的答案和一些互联网搜索。

use rocket::fairing::{Fairing, Info, Kind};
use rocket::http::Header;
use rocket::log::private::debug;
use rocket::serde::json::Json;
use rocket::{Request, Response};

#[macro_use]
extern crate rocket;

#[launch]
fn rocket() -> _ {
    rocket::build()
        .attach(Cors)
        .mount("/", routes![index, all_options, insert])
}

/// Some getter
#[get("/")]
fn index() -> &'static str {
    "Hello CORS"
}

/// Some setter
#[post("/", data = "<data>")]
async fn insert(data: Json<Vec<String>>) {
    debug!("Received data");
}

/// Catches all OPTION requests in order to get the CORS related Fairing triggered.
#[options("/<_..>")]
fn all_options() {
    /* Intentionally left empty */
}

pub struct Cors;

#[rocket::async_trait]
impl Fairing for Cors {
    fn info(&self) -> Info {
        Info {
            name: "Cross-Origin-Resource-Sharing Fairing",
            kind: Kind::Response,
        }
    }

    async fn on_response<'r>(&self, _request: &'r Request<'_>, response: &mut Response<'r>) {
        response.set_header(Header::new("Access-Control-Allow-Origin", "*"));
        response.set_header(Header::new(
            "Access-Control-Allow-Methods",
            "POST, PATCH, PUT, DELETE, HEAD, OPTIONS, GET",
        ));
        response.set_header(Header::new("Access-Control-Allow-Headers", "*"));
        response.set_header(Header::new("Access-Control-Allow-Credentials", "true"));
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 上帝保佑你,伙计。 (4认同)

Ibr*_*med 9

为了让服务器提供外部 API,它需要能够处理跨域资源共享 (CORS)。CORS 是一种基于 HTTP 标头的机制,它允许服务器指示浏览器应允许加载资源的来源(域、协议或端口)。

您可以创建一个整流罩来为您的应用程序全局处理 CORS。一个非常宽松的版本如下,但当然,您必须根据您的特定应用程序进行定制:

use rocket::http::Header;
use rocket::{Request, Response};
use rocket::fairing::{Fairing, Info, Kind};

pub struct CORS;

impl Fairing for CORS {
    fn info(&self) -> Info {
        Info {
            name: "Add CORS headers to responses",
            kind: Kind::Response
        }
    }

    fn on_response(&self, request: &Request, response: &mut Response) {
        response.set_header(Header::new("Access-Control-Allow-Origin", "*"));
        response.set_header(Header::new("Access-Control-Allow-Methods", "POST, GET, PATCH, OPTIONS"));
        response.set_header(Header::new("Access-Control-Allow-Headers", "*"));
        response.set_header(Header::new("Access-Control-Allow-Credentials", "true"));
    }
}
Run Code Online (Sandbox Code Playgroud)

你只需要像这样连接整流罩:

rocket::ignite().attach(CORS)
Run Code Online (Sandbox Code Playgroud)

或者,您可以使用rocket_cors板条箱。

use rocket::http::Method;
use rocket_cors::{AllowedOrigins, CorsOptions};

let cors = CorsOptions::default()
    .allowed_origins(AllowedOrigins::all())
    .allowed_methods(
        vec![Method::Get, Method::Post, Method::Patch]
            .into_iter()
            .map(From::from)
            .collect(),
    )
    .allow_credentials(true);

rocket::ignite().attach(cors.to_cors().unwrap())
Run Code Online (Sandbox Code Playgroud)

您可以在此处了解有关 CORS 和访问控制标头的更多信息

  • 在 0.5 中,您需要在实现中添加 `#[rocket::async_trait]` 属性,并使 on_response `async` 具有生命周期。 (3认同)

Pep*_*rez 9

这对我来说很有效:

use rocket::http::Header;
use rocket::{Request, Response};
use rocket::fairing::{Fairing, Info, Kind};

pub struct CORS;

#[rocket::async_trait]
impl Fairing for CORS {
    fn info(&self) -> Info {
        Info {
            name: "Attaching CORS headers to responses",
            kind: Kind::Response
        }
    }

    async fn on_response<'r>(&self, _request: &'r Request<'_>, response: &mut Response<'r>) {
        response.set_header(Header::new("Access-Control-Allow-Origin", "*"));
        response.set_header(Header::new("Access-Control-Allow-Methods", "POST, GET, PATCH, OPTIONS"));
        response.set_header(Header::new("Access-Control-Allow-Headers", "*"));
        response.set_header(Header::new("Access-Control-Allow-Credentials", "true"));
    }
}
Run Code Online (Sandbox Code Playgroud)

并且您必须使用启动宏将其附加到函数中:

#[launch]
fn rocket() -> _ {
    rocket::build()
        .attach(CORS)
        .mount("/index", routes![index])
}
Run Code Online (Sandbox Code Playgroud)