imbolc / axum-client-ip

A client IP address extractor for Axum
MIT License
41 stars 13 forks source link

Testing procedure ? #26

Open TxMat opened 8 months ago

TxMat commented 8 months ago

Hi,

I am currently writing a program with your library but while writing test i found that it seems to be no method for forcing a wrong ip to check the behaviour of the program. is there something that i missed ? what are the solutions ?

async fn set_ready(secure_client_ip: SecureClientIp,  state: State<AppState>) -> (StatusCode, String) {
    info!("client ip: {}", secure_client_ip.0);
    if let Some(ip) = state.ip.get() {
        if *ip != secure_client_ip.0 {
            error!("ip mismatch: {} != {}", ip, secure_client_ip.0);
            (StatusCode::FORBIDDEN, "ip mismatch".to_string())
        } else {
            state.is_ready.store(true, Ordering::Relaxed);
            info!("received ready signal from {}", secure_client_ip.0);
            info!("ready !");
            (StatusCode::OK, "ready".to_string())
        }
    } else {
        (StatusCode::BAD_REQUEST, "ip not set yet".to_string())
    }
}

// ... //

#[tokio::test]
    async fn check_set_ready_with_incorrect_ip() {
        let server = setup_test_server();
        server.post("/set_ip").json(&IpAddr { ip: Ipv4Addr::new(127, 0, 0, 1) }).await;
        let res = server.post("/ready")
            .add_header("X-Real-Ip".parse().unwrap(), "12.12.12.12".parse().unwrap())
            .await;
        println!("{:?}", res);
        res.assert_status(StatusCode::FORBIDDEN); // fails here
    }

it seems that the ip source is set to ConnectInfo even if a header is set

(this method works for insecure client tho)

imbolc commented 8 months ago

The IP is certainly parsed from headers, so your approach is correct. But the provided example is too complex, as usual try to maximally simplify it to locate the bug.

TxMat commented 8 months ago

i'll write a fully working example at work Monday but just using this you should be able to reproduce

async fn set_ready(secure_client_ip: SecureClientIp,  state: State<AppState>) -> (StatusCode, String) {
    println!("client ip: {}", secure_client_ip.0); // does not output 12.12.12.12
}

// ... bind the route, create the test server using axum-test, add connexioninfo ext //

#[tokio::test]
    async fn test() {
        let server = setup_test_server();
        server.post("/ready")
            .add_header("X-Real-Ip".parse().unwrap(), "12.12.12.12".parse().unwrap())
            .await;
    }