alexcrichton / curl-rust

Rust bindings to libcurl
MIT License
1k stars 234 forks source link

How to get `CURL_VERSION_HTTPS_PROXY`, `CURL_VERSION_THREADSAFE` features #464

Closed jcamiel closed 1 year ago

jcamiel commented 1 year ago

Hi,

First of all, as a developer of Hurl, a big thanks for this crate. Our modest project could not exist without curl-rust. I try to mimic the output of curl --version (in https://github.com/Orange-OpenSource/hurl/issues/836) and would like to display the features supported by the libcurl used by hurl.

With curl for instance, we can have this output:

$ curl --version
curl 7.74.0 (aarch64-unknown-linux-gnu) libcurl/7.74.0 OpenSSL/1.1.1n zlib/1.2.11 brotli/1.0.9 libidn2/2.3.0 libpsl/0.21.0 (+libidn2/2.3.0) libssh2/1.9.0 nghttp2/1.43.0 librtmp/2.3
Release-Date: 2020-12-09
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps mqtt pop3 pop3s rtmp rtsp scp sftp smb smbs smtp smtps telnet tftp
Features: alt-svc AsynchDNS brotli GSS-API HTTP2 HTTPS-proxy IDN IPv6 Kerberos Largefile libz NTLM NTLM_WB PSL SPNEGO SSL TLS-SRP UnixSockets

My issue is with the line

Features: alt-svc AsynchDNS brotli GSS-API HTTP2 HTTPS-proxy IDN IPv6 Kerberos Largefile libz NTLM NTLM_WB PSL SPNEGO SSL TLS-SRP UnixSockets

With the apis in curl_rust I can construct a list of some features:

let version = curl::Version::get();
let all_features = HashMap::from([
        ("AsynchDNS", version.feature_async_dns()),
        ("Debug", version.feature_debug()),
        ("IDN", version.feature_idn()),
// etc...
let mut features: Vec<String> = vec![];
for (k, v) in all_features.iter() {
    if *v {
        features.push(k.to_string());
    }
}

But I don't see the way to get the information if, for instance, the features HTTPS-proxy is supported. There is no feature_https_proxy() method, nor raw access to the bitfields.

In lib.rs, I don't see the definition for CURL_VERSION_HTTPS_PROXY and I struggle to understand the "gap" in bit mask.

pub const CURL_VERSION_UNIX_SOCKETS: c_int = 1 << 19;
pub const CURL_VERSION_BROTLI: c_int = 1 << 23;
pub const CURL_VERSION_ALTSVC: c_int = 1 << 24;

Some other field are also absent, like CURL_VERSION_THREADSAFE for instance.

My issue shows for sure my poor comprehension of the build of curl-rust. I've the impression that the bindings have been written for a version of curl that have not yet defined this fields so I don't see any way to know if newer features are supported or not in a more recent libcurl.

Sorry for my not very clear issue!

sagebind commented 1 year ago

The bindings are manually curated and not comprehensive. We've generally only added bindings to curl-sys as needed (particularly when the safe curl crate decides to expose them) as the full libcurl API surface is very large. The skips just (usually) indicate that we have not defined constants for several valid libcurl flags.

We do accept contributions though to add bindings to things currently not exposed. The full list of version flags at least in the latest curl version can be found here.

Some version flags just haven't made too much sense to expose though because they aren't directly supported by this crate (take Brotli for example: https://github.com/alexcrichton/curl-rust/issues/458) and so it isn't currently possible to enable the feature unless you link to an existing libcurl build with that feature enabled.

I've the impression that the bindings have been written for a version of curl that have not yet defined this fields

Since we do support being dynamically linked to a system-wide version of libcurl which could be an unknown version, we do try to be very careful on bindings to ensure that the curl crate will work against a variety of libcurl versions. However, adding new flags is generally safe since old versions of libcurl will simply return an error for unrecognized flags; it is actual new symbols where more care must be taken.

jcamiel commented 1 year ago

@sagebind Thank you for you detailed explanation.

If I understand you correctly, can I propose a PR to add feature_https_proxy as a new method to ask for CURL_VERSION_HTTPS_PROXY?

Another question, I was wondering, would be possible to expose the raw features version bitfield (instead of adding more "semantic" features" like feature_foot

impl Version {
....
  fn features(&self) -> i32 {
  }
...
}

I can propose also another PR, if it is, of course, aligned with the curl_crate design / feature set.

jcamiel commented 1 year ago

Fixed by #468.