cloud-sdk-reqwest 0.20.0

Optional provider-neutral reqwest transport boundary for cloud-sdk.
Documentation
use cloud_sdk::transport::ResponseContentType;
use reqwest::header::{CONTENT_TYPE, HeaderMap};

use super::TransportError;

pub(crate) fn parse_response_content_type(
    headers: &HeaderMap,
) -> Result<Option<ResponseContentType>, TransportError> {
    let mut values = headers.get_all(CONTENT_TYPE).iter();
    let Some(value) = values.next() else {
        return Ok(None);
    };
    if values.next().is_some() {
        return Err(TransportError::InvalidResponseContentType);
    }
    let value = value
        .to_str()
        .map_err(|_| TransportError::InvalidResponseContentType)?;
    ResponseContentType::new(value)
        .map(Some)
        .map_err(|_| TransportError::InvalidResponseContentType)
}

#[cfg(test)]
mod tests {
    use reqwest::header::{CONTENT_TYPE, HeaderMap, HeaderValue};

    use super::parse_response_content_type;
    use crate::shared::TransportError;

    #[test]
    fn accepts_absent_or_one_valid_content_type() {
        let headers = HeaderMap::new();
        assert_eq!(parse_response_content_type(&headers), Ok(None));

        let mut headers = HeaderMap::new();
        headers.insert(
            CONTENT_TYPE,
            HeaderValue::from_static("application/json; charset=utf-8"),
        );
        let parsed = parse_response_content_type(&headers);
        assert!(parsed.is_ok());
        if let Ok(Some(parsed)) = parsed {
            assert_eq!(parsed.as_str(), "application/json; charset=utf-8");
        }
    }

    #[test]
    fn rejects_duplicate_or_malformed_content_types() {
        let mut headers = HeaderMap::new();
        headers.append(CONTENT_TYPE, HeaderValue::from_static("application/json"));
        headers.append(CONTENT_TYPE, HeaderValue::from_static("text/plain"));
        assert_eq!(
            parse_response_content_type(&headers),
            Err(TransportError::InvalidResponseContentType)
        );

        let mut headers = HeaderMap::new();
        headers.insert(
            CONTENT_TYPE,
            HeaderValue::from_static("application/json; charset"),
        );
        assert_eq!(
            parse_response_content_type(&headers),
            Err(TransportError::InvalidResponseContentType)
        );
    }
}