pacenotes_installer\http/
http_error.rs1const CANCELLED: &str = "cancelled";
2
3pub struct HttpError {
4 pub code: u32,
6 pub message: String,
8 pub status: Option<u16>,
10}
11
12impl HttpError {
13 pub(super) fn last(context: &str) -> HttpError {
15 let code = unsafe { windows_sys::Win32::Foundation::GetLastError() };
16 HttpError {
17 code,
18 message: format!("{context}: {} (0x{code:08X})", error_text(code)),
19 status: None,
20 }
21 }
22
23 pub fn parse(message: impl Into<String>) -> HttpError {
25 HttpError::logical(message, None)
26 }
27
28 pub(super) fn logical(message: impl Into<String>, status: Option<u16>) -> HttpError {
29 HttpError {
30 code: 0,
31 message: message.into(),
32 status,
33 }
34 }
35
36 pub fn cancelled() -> HttpError {
37 HttpError::logical(CANCELLED, None)
38 }
39
40 pub fn is_cancelled(&self) -> bool {
42 self.code == 0 && self.status.is_none() && self.message == CANCELLED
43 }
44
45 pub fn is_transient(&self) -> bool {
48 match self.status {
49 Some(status) => status == 408 || status == 429 || status >= 500,
50 None => self.code != 0,
51 }
52 }
53}
54
55fn error_text(code: u32) -> String {
58 let module = unsafe {
59 windows_sys::Win32::System::LibraryLoader::GetModuleHandleW(
60 crate::i18n::to_wide("winhttp.dll").as_ptr(),
61 )
62 };
63 let mut buffer = [0u16; 512];
64 let length = unsafe {
65 windows_sys::Win32::System::Diagnostics::Debug::FormatMessageW(
66 windows_sys::Win32::System::Diagnostics::Debug::FORMAT_MESSAGE_FROM_SYSTEM
67 | windows_sys::Win32::System::Diagnostics::Debug::FORMAT_MESSAGE_FROM_HMODULE
68 | windows_sys::Win32::System::Diagnostics::Debug::FORMAT_MESSAGE_IGNORE_INSERTS,
69 module as *const core::ffi::c_void,
70 code,
71 0,
72 buffer.as_mut_ptr(),
73 buffer.len() as u32,
74 core::ptr::null(),
75 )
76 };
77 if length == 0 {
78 return "unknown error".into();
79 }
80 String::from_utf16_lossy(&buffer[..length as usize])
81 .trim_end_matches(['\r', '\n', ' '])
82 .to_string()
83}