This is very strange; no single correct answer is found on the entire internet. im sure that this thread will help others .
I also did a search here and found only this: .
looking also into the examples also no single
simple example for this case
I don't know if this is the right answer. All I want to do is return custom body text in response middleware. What I have in the middleware part doesn't work because I don't know the right way to construct the result.
My motivation here to prevent the request from getting to the main services
Like filters in tomcat
so what i have is :
use std::{future::{ready, Ready}};
use actix_http::{header::{self, HeaderName, HeaderValue}};
use actix_web::{
dev::{self, Service, ServiceRequest, ServiceResponse, Transform},
Error,http::Method, HttpResponseBuilder, HttpResponse
};
use futures_util::future::LocalBoxFuture;
//use crate::constants;
pub struct Heartbeat;
impl<S, B> Transform<S, ServiceRequest> for Heartbeat
where
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
S::Future: 'static,
B: 'static,
{
type Response = ServiceResponse<B>;
type Error = Error;
type InitError = ();
type Transform = HeartMiddleware<S>;
type Future = Ready<Result<Self::Transform, Self::InitError>>;
fn new_transform(&self, service: S) -> Self::Future {
ready(Ok(HeartMiddleware { service }))
}
}
pub struct HeartMiddleware<S> {
service: S,
}
impl<S, B> Service<ServiceRequest> for HeartMiddleware<S>
where
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
S::Future: 'static,
B: 'static,
{
type Response = ServiceResponse<B>;
type Error = Error;
type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;
dev::forward_ready!(service);
fn call(&self, req: ServiceRequest) -> Self::Future {
let CONTANT_TYPE: &'static str = "content-type";
let TEXT_PLAIN: &'static str = "text/plain";
let condition = (Method::POST == req.method() ||
Method::GET == req.method() ||
Method::HEAD == req.method()) && req.path() == "/ping";
let fut = self.service.call(req);
let (request, _pl) = req.into_parts();
Box::pin(async move {
let mut res = fut.await?;
let headers = res.headers_mut();
headers.insert(
HeaderName::from_static(CONTANT_TYPE), HeaderValue::from_static(TEXT_PLAIN)
);
if condition {
//Building the response here theoretically should be as simple as this, but it's not..
let response = HttpResponseBuilder::new(res.status()).body("body test");
let service_res = ServiceResponse::new(r,response);
return Ok(service_res)
}
Err(actix_web::error::ErrorImATeapot("Tea"))
})
}
}
error :
error[E0658]: use of unstable library feature 'custom_mir': MIR is an implementation detail and extremely unstable
--> src\heartbeat.rs:1:35
|
1 | use std::{future::{ready, Ready}, intrinsics::mir::StaticMut};
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0271]: expected `[async block@src\heartbeat.rs:59:18: 78:10]` to be a future that resolves to `Result<ServiceResponse<B>, Error>`, but it resolves to `Result<ServiceResponse, Error>`
--> src\heartbeat.rs:59:9
|
35 | impl<S, B> Service<ServiceRequest> for HeartMiddleware<S>
| - this type parameter
...
59 | / Box::pin(async move {
60 | |
61 | | let mut res = fut.await?;
62 | | let r = res.into_parts().0;
... |
77 | | Err(actix_web::error::ErrorImATeapot("Tea"))
78 | | })
| |__________^ expected `Result<ServiceResponse<B>, Error>`, found `Result<ServiceResponse, Error>`
|
= note: expected enum `Result<ServiceResponse<B>, _>`
found enum `Result<ServiceResponse<BoxBody>, _>`
= note: required for the cast from `Pin<Box<[async block@src\heartbeat.rs:59:18: 78:10]>>` to `Pin<Box<(dyn futures_util::Future<Output = Result<ServiceResponse<B>, actix_web::Error>> + 'static)>>`
Some errors have detailed explanations: E0271, E0658.
For more information about an error, try `rustc --explain E0271`.
warning: `broker-service` (bin "broker-service") generated 5 warnings
error: could not compile `broker-service` (bin "broker-service") due to 2 previous errors; 5 warnings emitted
Thanks