use crate::http::{headers, StatusCode, Url};
use crate::middleware::{Middleware, Next, Request, Response};
use crate::{Client, Result};
const REDIRECT_CODES: &[StatusCode] = &[
StatusCode::MovedPermanently,
StatusCode::Found,
StatusCode::SeeOther,
StatusCode::TemporaryRedirect,
StatusCode::PermanentRedirect,
];
#[derive(Debug)]
pub struct Redirect {
attempts: u8,
}
impl Redirect {
pub fn new(attempts: u8) -> Self {
Redirect { attempts }
}
}
#[async_trait::async_trait]
impl Middleware for Redirect {
#[allow(missing_doc_code_examples)]
async fn handle(&self, mut req: Request, client: Client, next: Next<'_>) -> Result<Response> {
let mut redirect_count: u8 = 0;
while redirect_count < self.attempts {
redirect_count += 1;
let r: Request = req.clone();
let res: Response = client.send(r).await?;
if REDIRECT_CODES.contains(&res.status()) {
if let Some(location) = res.header(headers::LOCATION) {
*req.as_mut().url_mut() = Url::parse(location.last().as_str())?;
}
} else {
break;
}
}
Ok(next.run(req, client).await?)
}
}
impl Default for Redirect {
fn default() -> Self {
Self { attempts: 3 }
}
}