/// Make a request to the endpoint.
///
/// A bearer token will automatically be included.
/// In case the bearer token gets rejected a new one is requested, this retry mechanism works 3 times, after that the client returns an error.
///
/// Note: only status code  `200` returns `Ok`, the rest returns an `Err`
Make a request to the endpoint.
A bearer token will automatically be included.
In case the bearer token gets rejected a new one is requested, this retry mechanism works 3 times, after that the client returns an error.


Make a request to the endpoint . A bearer token will automatically be included . In case the bearer token gets rejected a new one is requested this retry mechanism works 3 times after that the client returns an error .
pub async fn request<R, ExtractFut, ExtractError>(
        &self,
        request_builder: impl RequestBuilder,
        response_builder: impl FnOnce(Response) -> ExtractFut,
    ) -> Result<R>
    where
        ExtractFut: Future<Output = Result<R, ExtractError>>,
        ExtractError: Error + Send + Sync + 'static,
    {
        // Ensure we don't attempt to make a request with an expired access token
        self.ensure_authenticated().await?;
        // Number of times we received unauthorized for a certain request
        // When we reach MAX_RETRY_COUNT we stop trying
        let mut unauthorized_retries = 0;
        loop {
            // Build the request
            let mut request = request_builder.build(self.http_client.clone())?;
            // Add the bearer token to the request headers
            let headers = request.headers_mut();
            headers.insert(
                "Authorization",
                format!("Bearer {}", self.credentials.read().await.access_token).parse()?,
            );
            // Execute the request
            let response = self.http_client.execute(request).await?;
            // When the server returns 200: return the deserialized json
            // When the server returns 401: refresh authentication and retry
            // In other cases, throw an error
            match response.status() {
                StatusCode::OK => return Ok(response_builder(response).await?),
                StatusCode::UNAUTHORIZED => {
                    // When we reached the maximum amount of retries: bail
                    if unauthorized_retries == MAX_RETRY_COUNT {
                        bail!(format!(
                            "Failed to authenticate, retries = {} ",
                            MAX_RETRY_COUNT
                        ))
                    }
                    // Increase the retry counter
                    unauthorized_retries += 1;
                    trace!("Unauthorized retry: {}", unauthorized_retries);
                    // If we have already retried once add some sleep time in between retries, we don't want to DDOS the oauth server
                    if unauthorized_retries > 1 {
                        let sleep_duration = 500 * unauthorized_retries as u64;
                        trace!("Sleeping for {}ms before retrying", sleep_duration);
                        sleep(Duration::from_millis(sleep_duration)).await;
                    }
                    // Refresh the bearer token
                    self.force_refresh_authentication().await?;
                }
                status_code => {
                    bail!("Unsupported status code (CODE={})", status_code.as_u16())
                }
            }
        }
    }
pub async fn request < R , ExtractFut , ExtractError > ( & self , request_builder : impl RequestBuilder , response_builder : impl FnOnce ( Response ) -> ExtractFut , ) -> Result < R > where ExtractFut : Future < Output = Result < R , ExtractError > > , ExtractError : Error + Send + Sync + ' static , { // Ensure we don't attempt to make a request with an expired access token self . ensure_authenticated ( ) . await ? ; // Number of times we received unauthorized for a certain request // When we reach MAX_RETRY_COUNT we stop trying let mut unauthorized_retries = 0 ; loop { // Build the request let mut request = request_builder . build ( self . http_client . clone ( ) ) ? ; // Add the bearer token to the request headers let headers = request . headers_mut ( ) ; headers . insert ( " " , format ! ( " " self credentials read ( ) await access_token ) . parse ( ) ? , ) ; // Execute the request let response = self . http_client . execute ( request ) . await ? ; // When the server returns 200: return the deserialized json // When the server returns 401: refresh authentication and retry // In other cases, throw an error match response . status ( ) { StatusCode :: OK => return Ok ( response_builder ( response ) . await ? ) , StatusCode :: UNAUTHORIZED => { // When we reached the maximum amount of retries: bail if unauthorized_retries == MAX_RETRY_COUNT { bail ! ( format ( " " MAX_RETRY_COUNT ) ) } // Increase the retry counter unauthorized_retries += 1 ; trace ! ( " " unauthorized_retries ) ; // If we have already retried once add some sleep time in between retries, we don't want to DDOS the oauth server if unauthorized_retries > 1 { let sleep_duration = 500 * unauthorized_retries as u64 ; trace ! ( " " sleep_duration ) ; sleep ( Duration :: from_millis ( sleep_duration ) ) . await ; } // Refresh the bearer token self . force_refresh_authentication ( ) . await ? ; } status_code => { bail ! ( " " status_code as_u16 ( ) ) } } } }
Make a request to the endpoint.
Make a request to the endpoint .
&self
request_builder
impl RequestBuilder
response_builder
impl FnOnce(Response) -> ExtractFut