Skip to content

Commit

Permalink
Merge pull request #662 from jbr/only-log-once
Browse files Browse the repository at this point in the history
Only run the log middleware once per request
  • Loading branch information
yoshuawuyts authored Jul 31, 2020
2 parents 0ff17a3 + 530f931 commit ed7ea86
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 6 deletions.
19 changes: 14 additions & 5 deletions src/log/middleware.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ use crate::{Middleware, Next, Request};

/// Log all incoming requests and responses.
///
/// This middleware is enabled by default in Tide.
/// This middleware is enabled by default in Tide. In the case of
/// nested applications, this middleware will only run once for each
/// request.
///
/// # Examples
///
Expand All @@ -16,6 +18,8 @@ pub struct LogMiddleware {
_priv: (),
}

struct LogMiddlewareHasBeenRun;

impl LogMiddleware {
/// Create a new instance of `LogMiddleware`.
#[must_use]
Expand All @@ -26,17 +30,22 @@ impl LogMiddleware {
/// Log a request and a response.
async fn log<'a, State: Clone + Send + Sync + 'static>(
&'a self,
ctx: Request<State>,
mut req: Request<State>,
next: Next<'a, State>,
) -> crate::Result {
let path = ctx.url().path().to_owned();
let method = ctx.method().to_string();
if req.ext::<LogMiddlewareHasBeenRun>().is_some() {
return Ok(next.run(req).await);
}
req.set_ext(LogMiddlewareHasBeenRun);

let path = req.url().path().to_owned();
let method = req.method().to_string();
log::info!("<-- Request received", {
method: method,
path: path,
});
let start = std::time::Instant::now();
let response = next.run(ctx).await;
let response = next.run(req).await;
let status = response.status();
if status.is_server_error() {
if let Some(error) = response.error() {
Expand Down
35 changes: 34 additions & 1 deletion tests/log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@ use async_std::prelude::*;
use std::time::Duration;

mod test_utils;
use test_utils::ServerTestingExt;

#[async_std::test]
async fn start_server_log() {
async fn log_tests() {
let mut logger = logtest::start();
test_server_listen(&mut logger).await;
test_only_log_once(&mut logger).await;
}

async fn test_server_listen(logger: &mut logtest::Logger) {
let port = test_utils::find_port().await;
let app = tide::new();
let res = app
Expand All @@ -23,3 +28,31 @@ async fn start_server_log() {
format!("Server listening on http://[::1]:{}", port)
);
}

async fn test_only_log_once(logger: &mut logtest::Logger) {
let mut app = tide::new();
app.at("/").nest({
let mut app = tide::new();
app.at("/").get(|_| async { Ok("nested") });
app
});
app.get("/").await;

let entries: Vec<_> = logger.collect();

assert_eq!(
1,
entries
.iter()
.filter(|entry| entry.args() == "<-- Request received")
.count()
);

assert_eq!(
1,
entries
.iter()
.filter(|entry| entry.args() == "--> Response sent")
.count()
);
}

0 comments on commit ed7ea86

Please sign in to comment.