/* This Source Code Form is subject to the terms of the Mozilla Public *License,v.2.0.IfacopyoftheMPLwasnotdistributedwiththis
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
//! Partial libcurl bindings with some wrappers for safe cleanup.
usecrate::std::path::Path; use libloading::{Library, Symbol}; use once_cell::sync::Lazy; use std::ffi::{c_char, c_long, c_uint, CStr, CString};
const CURL_LIB_NAMES: &[&str] = if cfg!(target_os = "linux") {
&[ "libcurl.so", "libcurl.so.4", // Debian gives libcurl a different name when it is built against GnuTLS "libcurl-gnutls.so", "libcurl-gnutls.so.4", // Older versions in case we find nothing better "libcurl.so.3", "libcurl-gnutls.so.3", // See above for Debian
]
} elseif cfg!(target_os = "macos") {
&[ "/usr/lib/libcurl.dylib", "/usr/lib/libcurl.4.dylib", "/usr/lib/libcurl.3.dylib",
]
} elseif cfg!(target_os = "windows") {
&["libcurl.dll", "curl.dll"]
} else {
&[]
};
// # Safety // Curl handles are safe to pass among threads: https://curl.se/libcurl/c/threadsafe.html. unsafeimpl Send for CurlHandle {} unsafeimpl Send for CurlMime {} unsafeimpl Send for CurlMimePart {} unsafeimpl Send for CurlSlist {}
pubfn set_postfields(&mutself, data: impl Into<Box<[u8]>>) -> std::io::Result<()> { let data = data.into(); let size: c_long = data.len().try_into().map_err(std::io::Error::other)?;
to_result(unsafe {
(self.lib.curl_easy_setopt)(self.handle, CURLOPT_POSTFIELDSIZE, size)
})?;
to_result(unsafe {
(self.lib.curl_easy_setopt)( self.handle,
CURLOPT_POSTFIELDS,
data.as_ptr() as *const c_char,
)
})?; self.postdata = Some(data);
Ok(())
}
/// Returns the response data on success. pubfn perform(&self) -> Result<Vec<u8>> { // Set error buffer, but degrade service if it doesn't work. letmut error_buffer = ErrorBuffer::default(); let error_buffer_set = unsafe {
(self.lib.curl_easy_setopt)( self.handle,
CURLOPT_ERRORBUFFER,
error_buffer.0.as_mut_ptr() as *mut c_char,
)
} == CURLE_OK;
// Set the write function to fill a Vec. If there is a panic, this might leave stale // pointers in the curl options, but they won't be used without another perform, at which // point they'll be overwritten. letmut data: Vec<u8> = Vec::new(); extern"C"fn write_callback(
data: *const u8,
size: usize,
nmemb: usize,
dest: &mut Vec<u8>,
) -> usize { let total = size * nmemb;
dest.extend(unsafe { std::slice::from_raw_parts(data, total) });
total
} unsafe {
to_result((self.lib.curl_easy_setopt)( self.handle,
CURLOPT_WRITEFUNCTION,
write_callback asextern"C"fn(*const u8, usize, usize, &mut Vec<u8>) -> usize,
))?;
to_result((self.lib.curl_easy_setopt)( self.handle,
CURLOPT_WRITEDATA,
&mut data as *mut _,
))?;
};
letmut result = to_result(unsafe { (self.lib.curl_easy_perform)(self.handle) });
// Clean up a bit by unsetting the write function and write data, though they won't be used // anywhere else. Ignore return values. unsafe {
(self.lib.curl_easy_setopt)( self.handle,
CURLOPT_WRITEFUNCTION,
std::ptr::null_mut::<()>(),
);
(self.lib.curl_easy_setopt)(self.handle, CURLOPT_WRITEDATA, std::ptr::null_mut::<()>());
}
impl Slist<'_> { pubfn append(&mutself, s: &str) -> Result<()> { let cs = CString::new(s).unwrap(); let new_handle = unsafe { (self.lib.curl_slist_append)(self.handle, cs.as_ptr()) }; if new_handle.0.is_null() { return Err(Error { // From source inspection, failure modes are all malloc errors, // which are more than likely only from OOM.
code: CURLE_OUT_OF_MEMORY,
error: Some(format!("failed to append {s} to slist")),
});
} self.handle = new_handle;
Ok(())
}
}
impl Drop for Slist<'_> { fn drop(&mutself) { unsafe { (self.lib.curl_slist_free_all)(self.handle) };
}
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet am 2026-08-24)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.