rust - rust 火箭响应工具显示由于要求冲突而导致的生命周期参数“r”
问题描述
我现在正在学习生锈。今天我面临一生的问题。我想在 rust Rocket 中实现一个 api 响应,我希望 http 响应使用我的自定义实体ApiResponse
。我将构建它来替换默认的火箭响应。这是我的代码:
use rocket::serde::Deserialize;
use rocket::serde::Serialize;
use rocket::response::Responder;
use rocket::{Request, Response};
use rocket::http::{Status, ContentType};
#[derive(Debug, PartialEq, Eq, Deserialize, Serialize)]
#[allow(non_snake_case)]
pub struct ApiResponse<T> {
pub body: T,
pub statusCode: String,
pub resultCode: String
}
impl<'r,T> Responder<'r,'r> for ApiResponse<T> {
fn respond_to(self, req: &Request) -> Result<Response<'r>, Status> {
Response::build_from(self.respond_to(req).unwrap())
.header(ContentType::JSON)
.ok()
}
}
impl<T> Default for ApiResponse<T> where T : Default{
fn default() -> Self {
ApiResponse{
body: T::default(),
statusCode: "200".to_string(),
resultCode: "200".to_string()
}
}
}
当我编译这段代码时,显示如下错误:
$ cargo build ‹ruby-2.7.2›
Compiling reddwarf_music v0.1.0 (/Users/dolphin/Documents/GitHub/reddwarf_music)
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'r` due to conflicting requirements
--> src/biz/music/../../model/response/api_response.rs:17:35
|
17 | Response::build_from(self.respond_to(req).unwrap())
| ^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime defined on the method body at 16:31...
--> src/biz/music/../../model/response/api_response.rs:16:31
|
16 | fn respond_to(self, req: &Request) -> Result<Response<'r>, Status> {
| ^^^^^^^
note: ...so that the type `rocket::Request<'_>` is not borrowed for too long
--> src/biz/music/../../model/response/api_response.rs:17:46
|
17 | Response::build_from(self.respond_to(req).unwrap())
| ^^^
note: but, the lifetime must be valid for the lifetime `'r` as defined on the impl at 15:6...
--> src/biz/music/../../model/response/api_response.rs:15:6
|
15 | impl<'r,T> Responder<'r,'r> for ApiResponse<T> {
| ^^
note: ...so that the expression is assignable
--> src/biz/music/../../model/response/api_response.rs:17:9
|
17 | / Response::build_from(self.respond_to(req).unwrap())
18 | | .header(ContentType::JSON)
19 | | .ok()
| |_________________^
= note: expected `Result<rocket::Response<'r>, _>`
found `Result<rocket::Response<'_>, _>`
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'r` due to conflicting requirements
--> src/biz/user/../../model/response/api_response.rs:17:35
|
17 | Response::build_from(self.respond_to(req).unwrap())
| ^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime defined on the method body at 16:31...
--> src/biz/user/../../model/response/api_response.rs:16:31
|
16 | fn respond_to(self, req: &Request) -> Result<Response<'r>, Status> {
| ^^^^^^^
note: ...so that the type `rocket::Request<'_>` is not borrowed for too long
--> src/biz/user/../../model/response/api_response.rs:17:46
|
17 | Response::build_from(self.respond_to(req).unwrap())
| ^^^
note: but, the lifetime must be valid for the lifetime `'r` as defined on the impl at 15:6...
--> src/biz/user/../../model/response/api_response.rs:15:6
|
15 | impl<'r,T> Responder<'r,'r> for ApiResponse<T> {
| ^^
note: ...so that the expression is assignable
--> src/biz/user/../../model/response/api_response.rs:17:9
|
17 | / Response::build_from(self.respond_to(req).unwrap())
18 | | .header(ContentType::JSON)
19 | | .ok()
| |_________________^
= note: expected `Result<rocket::Response<'r>, _>`
found `Result<rocket::Response<'_>, _>`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0495`.
error: could not compile `reddwarf_music`
(base)
我阅读了终身手册并试图理解这个问题。抱歉,我无法弄清楚我的代码哪里出错了,这似乎太复杂了。编译器告诉详细信息,但我仍然没有解决这个问题的线索。那么为什么会发生这种情况呢?我应该怎么做才能解决这个问题?我应该从这个问题中学到什么?我试图建立默认响应:
let response = Response::new();
Response::build_from(response).header(ContentType::JSON).ok()
有用。但是当我从我自己构建时ApiResponse
:
Response::build_from(self.respond_to(req).unwrap())
.header(ContentType::JSON)
.ok()
不工作。
解决方案
您在https://api.rocket.rs/master/rocket/response/trait.Responder.html有更多文档
这是特征签名
pub trait Responder<'r, 'o: 'r> {
fn respond_to(self, request: &'r Request<'_>) -> Result<'o>;
}
和文件说
// If the response contains no borrowed data.
impl<'r> Responder<'r, 'static> for A {
fn respond_to(self, _: &'r Request<'_>) -> response::Result<'static> {
todo!()
}
}
// If the response borrows from the request.
impl<'r> Responder<'r, 'r> for B<'r> {
fn respond_to(self, _: &'r Request<'_>) -> response::Result<'r> {
todo!()
}
}
// If the response is or wraps a borrow that may outlive the request.
impl<'r, 'o: 'r> Responder<'r, 'o> for &'o C {
fn respond_to(self, _: &'r Request<'_>) -> response::Result<'o> {
todo!()
}
}
// If the response wraps an existing responder.
impl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for D<R> {
fn respond_to(self, _: &'r Request<'_>) -> response::Result<'o> {
todo!()
}
}
在你的情况下,它可能是
impl<'r, T> Responder<'r,'static> for ApiResponse<T> {
fn respond_to(self, req: &'r Request<'_>) -> response::Result<'static> {
todo!()
}
}
现在,通常 Responder 的实现在您的情况下没有意义。此实现用于发出请求,而 ApiResponse 显然旨在存储响应。
查看字符串实现
impl<'r> Responder<'r, 'static> for String {
fn respond_to(self, _: &'r Request<'_>) -> response::Result<'static> {
Response::build()
.header(ContentType::Plain)
.sized_body(self.len(), Cursor::new(self))
.ok()
}
}
或 doc 命题
use std::io::Cursor;
use rocket::request::Request;
use rocket::response::{self, Response, Responder};
use rocket::http::ContentType;
struct Person {
name: String,
age: u16
}
impl<'r> Responder<'r, 'static> for Person {
fn respond_to(self, req: &'r Request<'_>) -> response::Result<'static> {
let string = format!("{}:{}", self.name, self.age);
//--------------------------------^----------^-------
Response::build_from(string.respond_to(req)?)
.raw_header("X-Person-Name", self.name)
.raw_header("X-Person-Age", self.age.to_string())
.header(ContentType::new("application", "x-person"))
.ok()
}
}
推荐阅读
- python - 获取 TypeError: sequence item 1: expected str instance, Timestamp found 会有什么问题?
- visual-studio - 扩展不起作用且选项未显示 Visual Studio 2019
- google-data-studio - Google Data Studio:排序堆积条形图
- unit-testing - redis mock 用于在 nestjs 中进行测试
- gradle - 无法编译不受支持的 invokespecial 使用
- javascript - 点击事件不起作用。对于少数元素,它是少数它不是
- c# - WPF:从代码隐藏中的 ListView DataTemplate 获取控件
- javascript - ExtJS 4.2 textfield 用两种颜色设置文本
- javascript - 为什么PHP收不到AJAX发出的post请求
- javascript - navigator.mediaDevices.getUserMedia 在 ios 设备中显示黑屏