Repository: Orange-OpenSource/hurl
File: packages/hurl/src/http/client.rs (Rust)

Code before:
        } else if line.starts_with("HTTP/1.1") {
            Ok(HttpVersion::Http11)
        } else if line.starts_with("HTTP/2") {
            Ok(HttpVersion::Http2)
        } else if line.starts_with("HTTP/3") {
            Ok(HttpVersion::Http3)
        } else {
            Err(HttpError::CouldNotParseResponse)
        }
    }

    /// Parse headers from libcurl responses.
    fn parse_response_headers(&mut self, lines: &[String]) -> HeaderVec {
        let mut headers = HeaderVec::new();
        for line in lines {
            if let Some(header) = Header::parse(line) {
                headers.push(header);
            }
        }
        headers
    }

    /// Parse primary IP into `http::response_ip::IpAddr`
    fn parse_primary_ip(&mut self) -> Result<IpAddr, HttpError> {
        match self.handle.primary_ip()? {
            Some(ip_from_curl) => Ok(IpAddr {
                raw: ip_from_curl.to_string(),
            }),
            None => Err(HttpError::NoPrimaryIpInResponse),
        }
    }

    /// Retrieves an optional location to follow
    ///
    /// You need:
    /// 1. the option follow_location set to true
    /// 2. a 3xx response code
    /// 3. a header Location
    fn follow_location(
        &mut self,
        request_url: &Url,
        response: &Response,
    ) -> Result<Option<Url>, HttpError> {
        let response_code = response.status;
        if !(300..400).contains(&response_code) {
            return Ok(None);
        }
        let Some(location) = response.headers.get(LOCATION) else {
            return Ok(None);
        };
        let url = request_url.join(&location.value)?;

Review comment (suggestion):
Also the name of the binding could simply be `Some(ip)` instead of `Some(ip_from_curl)`we can make it concise, and don't need to know that it comes from libcurl

Code after:
        } else if line.starts_with("HTTP/1.1") {
            Ok(HttpVersion::Http11)
        } else if line.starts_with("HTTP/2") {
            Ok(HttpVersion::Http2)
        } else if line.starts_with("HTTP/3") {
            Ok(HttpVersion::Http3)
        } else {
            Err(HttpError::CouldNotParseResponse)
        }
    }

    /// Parse headers from libcurl responses.
    fn parse_response_headers(&mut self, lines: &[String]) -> HeaderVec {
        let mut headers = HeaderVec::new();
        for line in lines {
            if let Some(header) = Header::parse(line) {
                headers.push(header);
            }
        }
        headers
    }

    /// Get the IP address of the last connection from libcurl
    fn primary_ip(&mut self) -> Result<IpAddr, HttpError> {
        match self.handle.primary_ip()? {
            Some(ip) => Ok(IpAddr::new(ip.to_string())),
            None => Err(HttpError::NoPrimaryIp),
        }
    }

    /// Retrieves an optional location to follow
    ///
    /// You need:
    /// 1. the option follow_location set to true
    /// 2. a 3xx response code
    /// 3. a header Location
    fn follow_location(
        &mut self,
        request_url: &Url,
        response: &Response,
    ) -> Result<Option<Url>, HttpError> {
        let response_code = response.status;
        if !(300..400).contains(&response_code) {
            return Ok(None);
        }
        let Some(location) = response.headers.get(LOCATION) else {
            return Ok(None);
        };
        let url = request_url.join(&location.value)?;
        Ok(Some(url))
    }