pub(crate) fn connect(
    mut unit: Unit,
) -> Result<Response, Error> {
    let mut history = HistoryVec::new();
    let mut resp = loop {
        let resp = connect_inner(&unit, &history)?;

        let (_version, status, _text) = resp.get_status_line()?;
        // handle redirects
        if !(300..399).contains(&status) || unit.agent.config.redirects == 0 {
            break resp;
        }
        if history.len() + 1 >= unit.agent.config.redirects as usize {
            return Err(ErrorKind::TooManyRedirects.new());
        }
        // the location header
        let location = match resp.header("location") {
            Some(l) => l,
            None => break resp,
        };

        let url = &unit.url;
        let method = &unit.method;
        // join location header to current url in case it is relative
        let new_url = url.join(location).map_err(|e| {
            ErrorKind::InvalidUrl
                .msg(&format!("Bad redirection: {}", location))
                .src(e)
        })?;

        // perform the redirect differently depending on 3xx code.
        let new_method = match status {
            // this is to follow how curl does it. POST, PUT etc change
            // to GET on a redirect.
            301 | 302 | 303 => match &method[..] {
                "GET" | "HEAD" => unit.method,
                _ => "GET".into(),
            },
            // never change the method for 307/308
            // only resend the request if it cannot have a body
            // NOTE: DELETE is intentionally excluded: https://stackoverflow.com/questions/299628
            307 | 308 if ["GET", "HEAD", "OPTIONS", "TRACE"].contains(&method.as_str()) => {
                unit.method
            }
            _ => break resp,
        };
        debug!("redirect {} {} -> {}", status, url, new_url);
        history.push(unit.url);
        unit.headers.retain(|h| h.name() != "Content-Length");

        // recreate the unit to get a new hostname and cookies for the new host.
        unit = Unit::new(
            &unit.agent,
            &new_method,
            &new_url,
            &unit.headers,
            unit.deadline,
        );
    };
    resp.history = history;
    Ok(resp)
}
/// Perform a connection. Follows redirects.
Perform a connection. Follows redirects.
Perform a connection . Follows redirects .
pub(crate) fn connect(
    mut unit: Unit,
) -> Result<Response, Error> {
    let mut history = HistoryVec::new();
    let mut resp = loop {
        let resp = connect_inner(&unit, &history)?;
        let (_version, status, _text) = resp.get_status_line()?;
        // handle redirects
        if !(300..399).contains(&status) || unit.agent.config.redirects == 0 {
            break resp;
        }
        if history.len() + 1 >= unit.agent.config.redirects as usize {
            return Err(ErrorKind::TooManyRedirects.new());
        }
        // the location header
        let location = match resp.header("location") {
            Some(l) => l,
            None => break resp,
        };
        let url = &unit.url;
        let method = &unit.method;
        // join location header to current url in case it is relative
        let new_url = url.join(location).map_err(|e| {
            ErrorKind::InvalidUrl
                .msg(&format!("Bad redirection: {}", location))
                .src(e)
        })?;
        // perform the redirect differently depending on 3xx code.
        let new_method = match status {
            // this is to follow how curl does it. POST, PUT etc change
            // to GET on a redirect.
            301 | 302 | 303 => match &method[..] {
                "GET" | "HEAD" => unit.method,
                _ => "GET".into(),
            },
            // never change the method for 307/308
            // only resend the request if it cannot have a body
            // NOTE: DELETE is intentionally excluded: https://stackoverflow.com/questions/299628
            307 | 308 if ["GET", "HEAD", "OPTIONS", "TRACE"].contains(&method.as_str()) => {
                unit.method
            }
            _ => break resp,
        };
        debug!("redirect {} {} -> {}", status, url, new_url);
        history.push(unit.url);
        unit.headers.retain(|h| h.name() != "Content-Length");
        // recreate the unit to get a new hostname and cookies for the new host.
        unit = Unit::new(
            &unit.agent,
            &new_method,
            &new_url,
            &unit.headers,
            unit.deadline,
        );
    };
    resp.history = history;
    Ok(resp)
}
pub ( crate ) fn connect ( mut unit : Unit , ) -> Result < Response , Error > { let mut history = HistoryVec :: new ( ) ; let mut resp = loop { let resp = connect_inner ( & unit , & history ) ? ; let ( _version , status , _text ) = resp . get_status_line ( ) ? ; // handle redirects if ! ( 300 .. 399 ) . contains ( & status ) || unit . agent . config . redirects == 0 { break resp ; } if history . len ( ) + 1 >= unit . agent . config . redirects as usize { return Err ( ErrorKind :: TooManyRedirects . new ( ) ) ; } // the location header let location = match resp . header ( " " ) { Some ( l ) => l , None => break resp , } ; let url = & unit . url ; let method = & unit . method ; // join location header to current url in case it is relative let new_url = url . join ( location ) . map_err ( | e | { ErrorKind :: InvalidUrl . msg ( & format ! ( " " location ) ) . src ( e ) } ) ? ; // perform the redirect differently depending on 3xx code. let new_method = match status { // this is to follow how curl does it. POST, PUT etc change // to GET on a redirect. 301 | 302 | 303 => match & method [ .. ] { " " | " " => unit . method , _ => " " . into ( ) , } , // never change the method for 307/308 // only resend the request if it cannot have a body // NOTE: DELETE is intentionally excluded: https://stackoverflow.com/questions/299628 307 | 308 if [ " " , " " , " " , " " ] . contains ( & method . as_str ( ) ) => { unit . method } _ => break resp , } ; debug ! ( " " status url new_url ) ; history . push ( unit . url ) ; unit . headers . retain ( | h | h . name ( ) != " " ) ; // recreate the unit to get a new hostname and cookies for the new host. unit = Unit :: new ( & unit . agent , & new_method , & new_url , & unit . headers , unit . deadline , ) ; } ; resp . history = history ; Ok ( resp ) }
Perform a connection.
Perform a connection .
unit
Unit
unit
Unit