From 518bf03e042b850802f66f951c3f370614ee3102 Mon Sep 17 00:00:00 2001 From: Matthew Esposito Date: Wed, 26 Jun 2024 08:05:22 -0400 Subject: [PATCH] fix(client): Add trace logging for ratelimit info, render error page if exceeded --- src/client.rs | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/src/client.rs b/src/client.rs index 6838423..1aeb10c 100644 --- a/src/client.rs +++ b/src/client.rs @@ -5,7 +5,7 @@ use hyper::client::HttpConnector; use hyper::{body, body::Buf, client, header, Body, Client, Method, Request, Response, Uri}; use hyper_rustls::HttpsConnector; use libflate::gzip; -use log::error; +use log::{error, trace}; use once_cell::sync::Lazy; use percent_encoding::{percent_encode, CONTROLS}; use serde_json::Value; @@ -304,7 +304,7 @@ fn request(method: &'static Method, path: String, redirect: bool, quarantine: bo } // Make a request to a Reddit API and parse the JSON response -#[cached(size = 100, time = 30, result = true)] +// #[cached(size = 100, time = 30, result = true)] pub async fn json(path: String, quarantine: bool) -> Result { // Closure to quickly build errors let err = |msg: &str, e: String, path: String| -> Result { @@ -317,9 +317,36 @@ pub async fn json(path: String, quarantine: bool) -> Result { Ok(response) => { let status = response.status(); + // Ratelimit remaining + if let Some(Ok(remaining)) = response.headers().get("x-ratelimit-remaining").map(|val| val.to_str()) { + trace!("Ratelimit remaining: {}", remaining); + } + + // Ratelimit used + if let Some(Ok(used)) = response.headers().get("x-ratelimit-used").map(|val| val.to_str()) { + trace!("Ratelimit used: {}", used); + } + + // Ratelimit reset + let reset = if let Some(Ok(reset)) = response.headers().get("x-ratelimit-reset").map(|val| val.to_str()) { + trace!("Ratelimit reset: {}", reset); + Some(reset.to_string()) + } else { + None + }; + // asynchronously aggregate the chunks of the body match hyper::body::aggregate(response).await { Ok(body) => { + let has_remaining = body.has_remaining(); + + if !has_remaining { + return match reset { + Some(val) => Err(format!("Reddit rate limit exceeded. Will reset in: {val}")), + None => Err("Reddit rate limit exceeded".to_string()), + }; + } + // Parse the response from Reddit as JSON match serde_json::from_reader(body.reader()) { Ok(value) => {