I have a rocket (0.5.0-rc.1
) route, that returns a content::Json<String>
and I would like to add CORS to that route using rocket_cors
(from master).
Specifically I want to use the RequestGuard
, because I only want to enable CORS for certain routes.
My original request looked like this:
#[get("/json")]
fn json_without_cors() -> content::Json<String> {
let test = Test {
field1: 0,
field2: String::from("Test"),
};
let json = serde_json::to_string(&test).expect("Failed to encode data.");
content::Json(json)
}
and I changed it to use CORS (based on this example) like so
#[get("/json")]
fn json(cors: Guard<'_>) -> Responder<'_, '_, content::Json<String>> {
let test = Test {
field1: 0,
field2: String::from("Test"),
};
let json = serde_json::to_string(&test).expect("Failed to encode data.");
cors.responder(content::Json(json))
}
Unfortunately this now fails to compile with:
error[E0621]: explicit lifetime required in the type of `cors`
--> src/main.rs:35:10
|
28 | fn json(cors: Guard<'_>) -> Responder<'_, '_, content::Json<String>> {
| --------- help: add explicit lifetime `'static` to the type of `cors`: `Guard<'static>`
...
35 | cors.responder(content::Json(json))
| ^^^^^^^^^ lifetime `'static` required
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0621, E0759.
For more information about an error, try `rustc --explain E0621`.
error: could not compile `cors_json`
I can't give Guard
a 'static
lifetime, because this leads to further issues down the road.
How can I return a content::Json<String>
from my request with CORS?
A full example can be found on Github.
It's due to the fact that rocket_cors
has lifetime bounds on the Responder
struct, and these make the struct covariant on these lifetime bounds (so it makes it reject a 'static
lifetime when it shouldn't).
The good news is that these bounds are not necessary on the struct's declaration since they can exist solely on the related impl
blocks.
I've created a pull request, but this will be a breaking API change since Responder
will no longer be directly generic over these lifetimes. If you want to keep tracking their master branch, you can do what @Hadus suggested and pass a 'static
as the Responder's lifetime param.
Using the PR's branch you can directly do:
#[get("/json")]
fn json(cors: Guard<'_>) -> Responder<content::Json<String>> {
let test = Test {
field1: 0,
field2: String::from("Test"),
};
let json = serde_json::to_string(&test).expect("Failed to encode data.");
cors.responder(content::Json(json))
}
Update: It's been merged.