-
Okay, I'm going to sound like a total noob asking this but it's day 2 of my Rust learning! I've got a graphql server up and running okay with actix-web and jupiter - works beautifully and compared to GoLang, getting it up and running was a dream! But while playing about I wanted to see if I could log the body of requests. Now I've probably done this totally wrong, so please don't flame me :D, but from what I gather I can add extra logging info to the middleware logger using Where I'm totally puzzled is taking the payload data from I think if I saw how a pro would do it it would really help me out. I've searched for answers but can't seem to find anything. Probably because it's not the done thing to be logging the payloads, but like I say, this is more about knowing how it would be done. Would really appreciate any guidance #[actix_web::main]
async fn main() -> std::io::Result<()> {
std::env::set_var("RUST_LOG", "warning,actix_web=info");
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
dotenv::dotenv().ok();
let port = dotenv::var("HTTP_PORT").unwrap_or("8081".to_owned());
let host = dotenv::var("HTTP_HOST").unwrap_or("127.0.0.1".to_owned());
log::info!("starting HTTP server on port {port}");
log::info!("GraphQL playground: http://localhost:{port}/playground");
let app_state = Data::new(AppState {
app_name: "My GQL API".to_string(),
db_pool: db::get_db_clients().await
});
HttpServer::new(move || {
App::new()
.app_data(app_state.clone())
.configure(register)
.wrap(Cors::permissive())
.wrap(Logger::new("%{REQ_PAYLOAD}xi")
.custom_request_replace("REQ_PAYLOAD", | req | {
let (_, payload) = req.into_parts();
... // hmmm
}))
})
.workers(2)
.bind(format!("{host}:{port}"))?
.run()
.await
} |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
There's no way to read the payload when you only have a If you want to do this, I'd suggest logging the query within your GraphQL handler, since middleware is designed more to apply to a large range of endpoints. Alternatively, a middleware around the specific GraphQL handler that does this separately. Using Roughly (untested): async fn log_gql_query<B>(
query: String,
mut req: ServiceRequest,
next: Next<B>,
) -> Result<ServiceResponse<B>, Error> {
log::debug!("GraphQL query: {query}");
let mut body = actix_http::h1::Payload::create(true);
body.unread_data(query.into());
std::mem::replace(req.parts_mut().1, body);
next.call(req).await
}
...
web::resource("/graphql")
.route(web::post().wrap(from_fn(log_gql_query)).to(...)) |
Beta Was this translation helpful? Give feedback.
There's no way to read the payload when you only have a
&ServiceRequest
, as is the case here. That's because, at the middleware level, all payloads are streams that are yet to be read.If you want to do this, I'd suggest logging the query within your GraphQL handler, since middleware is designed more to apply to a large range of endpoints.
Alternatively, a middleware around the specific GraphQL handler that does this separately. Using
from_fn
from actix-web-lab make this a breeze because you can use extractors, though you need to "re-insert" the body which is a little hacky.Roughly (untested):