Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(error)!: more specific errors including their source #252

Merged
merged 3 commits into from
Jan 31, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ unsafe_code = "forbid"
[lints.clippy]
pedantic = { level = "warn", priority = -1 }
nursery = { level = "warn", priority = -1 }
result_large_err = "allow" # due to ureq::Error
struct_excessive_bools = "allow" # due to Telegram API

# TODO: remove and fix (or allow explicitly on the specific problem)
Expand Down
39 changes: 14 additions & 25 deletions src/client_reqwest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,31 +39,24 @@ impl AsyncApi {
Self::builder().api_url(api_url).build()
}

pub async fn decode_response<Output>(response: reqwest::Response) -> Result<Output, Error>
async fn decode_response<Output>(response: reqwest::Response) -> Result<Output, Error>
where
Output: serde::de::DeserializeOwned,
{
let status_code = response.status().as_u16();
match response.text().await {
Ok(message) => {
if status_code == 200 {
Ok(crate::json::decode(&message)?)
} else {
Err(Error::Api(crate::json::decode(&message)?))
}
}
Err(error) => Err(Error::Decode(format!("{error:?}"))),
let success = response.status().is_success();
let message = response.text().await?;
if success {
Ok(crate::json::decode(&message)?)
} else {
Err(Error::Api(crate::json::decode(&message)?))
}
}
}

impl From<reqwest::Error> for Error {
fn from(error: reqwest::Error) -> Self {
let message = error.to_string();
let code = error
.status()
.map_or(500, |status_code| status_code.as_u16());
Self::Http { code, message }
// Prevent leakage of the bot token as its within the path
Self::HttpReqwest(error.without_url())
}
}

Expand Down Expand Up @@ -95,6 +88,7 @@ impl AsyncTelegramApi for AsyncApi {
Self::decode_response(response).await
}

#[cfg_attr(target_arch = "wasm32", allow(unused_variables))]
async fn request_with_form_data<Params, Output>(
&self,
method: &str,
Expand Down Expand Up @@ -140,7 +134,7 @@ impl AsyncTelegramApi for AsyncApi {
for (parameter_name, file_path, file_name) in files_with_paths {
let file = tokio::fs::File::open(file_path)
.await
.map_err(|error| Error::Encode(error.to_string()))?;
.map_err(Error::ReadFile)?;
let part = multipart::Part::stream(file).file_name(file_name);
form = form.part(parameter_name, part);
}
Expand All @@ -152,19 +146,14 @@ impl AsyncTelegramApi for AsyncApi {
}

#[cfg(target_arch = "wasm32")]
{
Err(Error::Encode(format!(
"calling {method:?} with files is currently unsupported in WASM due to missing form_data / attachment support. Was called with params {params:?} and files {files:?}",
)))
}
Err(Error::WasmHasNoFileSupportYet)
}
}

#[cfg(test)]
mod async_tests {
mod tests {
use super::*;
use crate::api_params::SendMessageParams;
use crate::json;

#[tokio::test]
async fn async_send_message_success() {
Expand All @@ -186,7 +175,7 @@ mod async_tests {
mock.assert();
drop(server);

json::assert_str(&response, response_string);
crate::test_json::assert_json_str(&response, response_string);
}

#[tokio::test]
Expand Down
Loading
Loading