如何为 Rocket.rs 设置 CORS 或 OPTIONS
How to set up CORS or OPTIONS for Rocket.rs
我有一个后端 运行 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>
我已将以下内容添加到我的火箭项目中:
#[options("/")]
fn send_options<'a>(path: PathBuf) -> Response<'a> {
let mut res = Response::new();
res.set_status(Status::new(200, "No Content"));
res.adjoin_header(ContentType::Plain);
res.adjoin_raw_header("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
res.adjoin_raw_header("Access-Control-Allow-Origin", "*");
res.adjoin_raw_header("Access-Control-Allow-Credentials", "true");
res.adjoin_raw_header("Access-Control-Allow-Headers", "Content-Type");
res
我的 flutter 应用是 运行 这个请求:
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;
}
问题:这是响应 OPTION 请求的正确方法吗?如果不是,我如何在 rocket.rs 中实现它?
Lambda Fairy 的评论帮我解答了。
我把它全部放在 GET
处理程序中:
#[get("/")]
fn get_handler<'a>() -> Response<'a> {
let mut res = Response::new();
res.set_status(Status::new(200, "No Content"));
res.adjoin_header(ContentType::Plain);
res.adjoin_raw_header("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
res.adjoin_raw_header("Access-Control-Allow-Origin", "*");
res.adjoin_raw_header("Access-Control-Allow-Credentials", "true");
res.adjoin_raw_header("Access-Control-Allow-Headers", "Content-Type");
res.set_sized_body(Cursor::new("Response"));
res
为了让服务器提供外部 API 它需要能够处理跨源资源共享 (CORS)。 CORS 是一种基于 HTTP-header 的机制,它允许服务器指示浏览器应允许加载资源的来源(域、协议或端口)。
您可以创建一个整流罩来为您的应用全局处理 CORS。一个非常宽松的版本如下,但当然,您必须根据您的特定应用程序进行定制。
火箭 0.4
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"));
}
}
火箭 0.5
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: "Add 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"));
}
}
您只需像这样安装整流罩:
rocket::ignite().attach(CORS)
或者,您可以使用 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())
您可以了解有关 CORS 和访问控制的更多信息 headers here
这对我有用:
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"));
}
}
并且您必须使用启动宏将其附加到函数中:
#[launch]
fn rocket() -> _ {
rocket::build()
.attach(CORS)
.mount("/index", routes![index])
}
要获得跨源资源共享支持,您必须拦截响应
由您的 Rocket 服务器发送。你想实现一个中间件来实现它,
在 Rocket 上,你必须在 struct
上实现 Fairing
特性才能
做到这一点。
Rocket v0.5.x(不稳定)
如果您在 Rocket 的文档中搜索版本 0。5.x。
Trait implemented by fairings: Rocket’s structured middleware.
You must decorate the Fairing
trait
implementation with the rocket::async-trait
attribute.
use rocket::fairing::{Fairing, Info, Kind};
use rocket::http::Header;
use rocket::{Request, Response};
pub struct Cors;
#[rocket::async_trait]
impl Fairing for Cors {
fn info(&self) -> Info {
Info {
name: "Cross-Origin-Resource-Sharing Middleware",
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",
"https://example.com",
));
response.set_header(Header::new(
"access-control-allow-methods",
"GET, PATCH, OPTIONS",
));
}
}
在您的 main.rs
文件中,您必须附加中间件:
mod config;
mod middleware;
mod routes;
use self::config::Config;
#[macro_use]
extern crate rocket;
#[launch]
async fn rocket() -> _ {
let config = Config::new();
rocket::custom(&config.server_config)
.attach(middleware::cors::Cors)
.mount(
"/api/v1",
routes![routes::index],
)
}
火箭 0.4.x(稳定)
参考
万一有人找火箭>=rc5.0
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: "Add CORS headers to responses",
kind: Kind::Response
}
}
async fn on_response<'r>(&self, req: &'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"));
}
}
耶稣。几个小时后,我终于让它工作了。首先,一个小警告:我们正在处理高度不稳定的代码,这个答案在您阅读时可能已经过时。 Ibraheem Ahmeed 的回答中 matthewscottgordon 的编辑为我指明了正确的方向。
我们将使用 rocket_cors
箱子。
1。安装旧版本的 Rust Nightly。截至 1 月 22 日,Rust Nightly V 1.6.0 中断 mongodb 2.1.0.
执行此操作以防最新的每晚未编译。
您可以按以下方式执行此操作:
rustup override set nightly-2021-11-10
This will download 1.58 nightly.
2。添加 rocket_cors 依赖项。截至目前,主版本有 1.6.0 版本,目标是 rocket 的 0.5.0-rc.1 版本
rocket_cors = { git = "https://github.com/lawliet89/rocket_cors", branch = "master" }
这是我的 cargo.toml:
[dependencies]
rocket = {version ="0.5.0-rc.1", features=["json"]}
rocket_cors = { git = "https://github.com/lawliet89/rocket_cors", branch = "master" }
reqwest = {version = "0.11.6", features = ["json"] }
serde= {version = "1.0.117", features= ["derive"]}
mongodb = "2.1.0"
rand = "0.8.4"
3。将以下内容添加到您的主要 Rocket 函数中:
extern crate rocket;
use std::error::Error;
use rocket_cors::{AllowedOrigins, CorsOptions};
#[rocket::main]
async fn main() -> Result<(), Box<dyn Error>> {
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)
.to_cors()?;
// let path = concat!(env!("CARGO_MANIFEST_DIR"), "/public");
rocket::build()
.mount("/", routes![index, upload::upload, post_favorites])
.attach(cors)
.launch()
.await?;
Ok(())
}
如果这个答案对您不起作用,请务必查看rocket_cors repository for up to date examples. The example above was used with the fairing.rs文件
查看存储库的 Cargo.toml 文件。
要检查 let cors
中的默认值,(如果使用 VS Code 和 Rust 扩展)将鼠标悬停在 CorsOptions
上。
我有一个后端 运行 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>
我已将以下内容添加到我的火箭项目中:
#[options("/")]
fn send_options<'a>(path: PathBuf) -> Response<'a> {
let mut res = Response::new();
res.set_status(Status::new(200, "No Content"));
res.adjoin_header(ContentType::Plain);
res.adjoin_raw_header("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
res.adjoin_raw_header("Access-Control-Allow-Origin", "*");
res.adjoin_raw_header("Access-Control-Allow-Credentials", "true");
res.adjoin_raw_header("Access-Control-Allow-Headers", "Content-Type");
res
我的 flutter 应用是 运行 这个请求:
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;
}
问题:这是响应 OPTION 请求的正确方法吗?如果不是,我如何在 rocket.rs 中实现它?
Lambda Fairy 的评论帮我解答了。
我把它全部放在 GET
处理程序中:
#[get("/")]
fn get_handler<'a>() -> Response<'a> {
let mut res = Response::new();
res.set_status(Status::new(200, "No Content"));
res.adjoin_header(ContentType::Plain);
res.adjoin_raw_header("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
res.adjoin_raw_header("Access-Control-Allow-Origin", "*");
res.adjoin_raw_header("Access-Control-Allow-Credentials", "true");
res.adjoin_raw_header("Access-Control-Allow-Headers", "Content-Type");
res.set_sized_body(Cursor::new("Response"));
res
为了让服务器提供外部 API 它需要能够处理跨源资源共享 (CORS)。 CORS 是一种基于 HTTP-header 的机制,它允许服务器指示浏览器应允许加载资源的来源(域、协议或端口)。
您可以创建一个整流罩来为您的应用全局处理 CORS。一个非常宽松的版本如下,但当然,您必须根据您的特定应用程序进行定制。
火箭 0.4
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"));
}
}
火箭 0.5
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: "Add 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"));
}
}
您只需像这样安装整流罩:
rocket::ignite().attach(CORS)
或者,您可以使用 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())
您可以了解有关 CORS 和访问控制的更多信息 headers here
这对我有用:
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"));
}
}
并且您必须使用启动宏将其附加到函数中:
#[launch]
fn rocket() -> _ {
rocket::build()
.attach(CORS)
.mount("/index", routes![index])
}
要获得跨源资源共享支持,您必须拦截响应
由您的 Rocket 服务器发送。你想实现一个中间件来实现它,
在 Rocket 上,你必须在 struct
上实现 Fairing
特性才能
做到这一点。
Rocket v0.5.x(不稳定)
如果您在 Rocket 的文档中搜索版本 0。5.x。
Trait implemented by fairings: Rocket’s structured middleware.
You must decorate the
Fairing
trait
implementation with the rocket::async-trait attribute.
use rocket::fairing::{Fairing, Info, Kind};
use rocket::http::Header;
use rocket::{Request, Response};
pub struct Cors;
#[rocket::async_trait]
impl Fairing for Cors {
fn info(&self) -> Info {
Info {
name: "Cross-Origin-Resource-Sharing Middleware",
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",
"https://example.com",
));
response.set_header(Header::new(
"access-control-allow-methods",
"GET, PATCH, OPTIONS",
));
}
}
在您的 main.rs
文件中,您必须附加中间件:
mod config;
mod middleware;
mod routes;
use self::config::Config;
#[macro_use]
extern crate rocket;
#[launch]
async fn rocket() -> _ {
let config = Config::new();
rocket::custom(&config.server_config)
.attach(middleware::cors::Cors)
.mount(
"/api/v1",
routes![routes::index],
)
}
火箭 0.4.x(稳定)
参考
万一有人找火箭>=rc5.0
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: "Add CORS headers to responses",
kind: Kind::Response
}
}
async fn on_response<'r>(&self, req: &'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"));
}
}
耶稣。几个小时后,我终于让它工作了。首先,一个小警告:我们正在处理高度不稳定的代码,这个答案在您阅读时可能已经过时。 Ibraheem Ahmeed 的回答中 matthewscottgordon 的编辑为我指明了正确的方向。
我们将使用 rocket_cors
箱子。
1。安装旧版本的 Rust Nightly。截至 1 月 22 日,Rust Nightly V 1.6.0 中断 mongodb 2.1.0.
执行此操作以防最新的每晚未编译。
您可以按以下方式执行此操作:
rustup override set nightly-2021-11-10 This will download 1.58 nightly.
2。添加 rocket_cors 依赖项。截至目前,主版本有 1.6.0 版本,目标是 rocket 的 0.5.0-rc.1 版本
rocket_cors = { git = "https://github.com/lawliet89/rocket_cors", branch = "master" }
这是我的 cargo.toml:
[dependencies]
rocket = {version ="0.5.0-rc.1", features=["json"]}
rocket_cors = { git = "https://github.com/lawliet89/rocket_cors", branch = "master" }
reqwest = {version = "0.11.6", features = ["json"] }
serde= {version = "1.0.117", features= ["derive"]}
mongodb = "2.1.0"
rand = "0.8.4"
3。将以下内容添加到您的主要 Rocket 函数中:
extern crate rocket;
use std::error::Error;
use rocket_cors::{AllowedOrigins, CorsOptions};
#[rocket::main]
async fn main() -> Result<(), Box<dyn Error>> {
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)
.to_cors()?;
// let path = concat!(env!("CARGO_MANIFEST_DIR"), "/public");
rocket::build()
.mount("/", routes![index, upload::upload, post_favorites])
.attach(cors)
.launch()
.await?;
Ok(())
}
如果这个答案对您不起作用,请务必查看rocket_cors repository for up to date examples. The example above was used with the fairing.rs文件
查看存储库的 Cargo.toml 文件。
要检查 let cors
中的默认值,(如果使用 VS Code 和 Rust 扩展)将鼠标悬停在 CorsOptions
上。