Skip to content

Redirects are not passed through the middleware #248

@lukaslihotzki-f

Description

@lukaslihotzki-f

Bug description

Redirects are opaque to the middleware stack. This breaks caching (06chaynes/http-cache#117). Additionally, retries are probably more expensive than needed, but I didn't check this.

To Reproduce

PrintMiddleware::handle is printed only once, even though Status: 200 indicates that a redirect was followed.

use http::Extensions;
use reqwest::Client;
use reqwest::{Request, Response};
use reqwest_middleware::ClientBuilder;
use reqwest_middleware::{Middleware, Next, Result};
use wiremock::{matchers::path, Mock, MockServer, ResponseTemplate};

#[derive(Debug)]
pub struct PrintMiddleware;

#[async_trait::async_trait]
impl Middleware for PrintMiddleware {
    async fn handle(
        &self,
        req: Request,
        extensions: &mut Extensions,
        next: Next<'_>,
    ) -> Result<Response> {
        println!("PrintMiddleware::handle");
        next.run(req, extensions).await
    }
}

#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<()> {
    // Setup mock server with cacheable response
    let mock_server = MockServer::start().await;
    Mock::given(path("/"))
        .respond_with(
            ResponseTemplate::new(307)
                .set_body_string("Hello from cached response!")
                .append_header("cache-control", "no-cache, no-store")
                .append_header("location", "/final")
                .append_header("content-type", "text/plain"),
        )
        .mount(&mock_server)
        .await;

    Mock::given(path("/final"))
        .respond_with(
            ResponseTemplate::new(200)
                .set_body_string("Hello from cached response!")
                .append_header("cache-control", "max-age=300, public")
                .append_header("content-type", "text/plain"),
        )
        .mount(&mock_server)
        .await;

    let client = ClientBuilder::new(Client::new())
        .with(PrintMiddleware)
        .build();

    let response = client.get(&mock_server.uri()).send().await?;

    println!("Status: {}", response.status().as_u16());

    Ok(())
}

Expected behavior

The middleware should be called for each request of a redirect chain.

Environment

  • OS: Linux
  • Rust version 1.89.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions