From 31977f9642d61885543da109dc3f7972bf3250f7 Mon Sep 17 00:00:00 2001 From: sigoden Date: Sat, 18 May 2024 22:41:27 +0800 Subject: [PATCH] fix: panic when check api error (#520) --- src/client/common.rs | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/src/client/common.rs b/src/client/common.rs index 4ef276d..73ed40a 100644 --- a/src/client/common.rs +++ b/src/client/common.rs @@ -482,16 +482,24 @@ pub fn catch_error(data: &Value, status: u16) -> Result<()> { } debug!("Invalid response, status: {status}, data: {data}"); if let Some(error) = data["error"].as_object() { - if let (Some(typ), Some(message)) = (error["type"].as_str(), error["message"].as_str()) { + if let (Some(typ), Some(message)) = ( + get_str_field_from_json_map(error, "type"), + get_str_field_from_json_map(error, "message"), + ) { bail!("{message} (type: {typ})"); } } else if let Some(error) = data["errors"][0].as_object() { - if let (Some(code), Some(message)) = (error["code"].as_u64(), error["message"].as_str()) { + if let (Some(code), Some(message)) = ( + get_u64_field_from_json_map(error, "code"), + get_str_field_from_json_map(error, "message"), + ) { bail!("{message} (status: {code})") } } else if let Some(error) = data[0]["error"].as_object() { - if let (Some(status), Some(message)) = (error["status"].as_str(), error["message"].as_str()) - { + if let (Some(status), Some(message)) = ( + get_str_field_from_json_map(error, "status"), + get_str_field_from_json_map(error, "message"), + ) { bail!("{message} (status: {status})") } } else if let (Some(detail), Some(status)) = (data["detail"].as_str(), data["status"].as_i64()) @@ -505,6 +513,20 @@ pub fn catch_error(data: &Value, status: u16) -> Result<()> { bail!("Invalid response data: {data} (status: {status})"); } +pub fn get_str_field_from_json_map<'a>( + map: &'a serde_json::Map, + field_name: &str, +) -> Option<&'a str> { + map.get(field_name).and_then(|v| v.as_str()) +} + +pub fn get_u64_field_from_json_map( + map: &serde_json::Map, + field_name: &str, +) -> Option { + map.get(field_name).and_then(|v| v.as_u64()) +} + pub fn maybe_catch_error(data: &Value) -> Result<()> { if let (Some(code), Some(message)) = (data["code"].as_str(), data["message"].as_str()) { debug!("Invalid response: {}", data);