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

add mime support (form api is deprecated according to libcurl) #537

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

tsnoam
Copy link

@tsnoam tsnoam commented Nov 26, 2023

libcurl considers the form api deprecated.
in curl_formadd(3) one of the first lines says:

This function is deprecated. Use curl_mime_init(3) instead.

This pull requests implements a safe wrapper of the mime api, keeping simplicity in mind. Usage is quite straight forward.

The following example is a bit simplified (lot of unwraps, usage of &str where possible.

fn main() {
    let filenames = &[ "/path/to/file1", "/path/to/file2" ];
    curl::init();
    let mut client = curl::easy::Easy::new();

    // interesting part starts here

    let mut mime = client.add_mime();
    for fname in filenames.iter() {
        let buf = read_file(fname)?;  // 
        mime.add_part()
            .set_name("some-name").unwrap()
            .set_filename(fname.rsplit_once('/').unwrap().1).unwrap()
            .set_data(buf).unwrap()
            .set_content_type("application/octet-stream").unwrap();
    }
    mime.post()?;

    // make sure not to call client.post/get/put/custom_request() as it will modify stuff inside libcurl causing it to behave
    // not as you intended (this comment is also true fort the deprecated form api)

    // interesting part ends here

    client.url("http://127.0.0.1/").unwrap();
    client.perform().unwrap();
}

/// Read a file into Vec<u8> - implementation is an exercise for the reader
fn read_file(fname: &str) -> Result<Vec<u8>, Error> {
    todo!();
}

@tsnoam tsnoam force-pushed the mimepart branch 2 times, most recently from e0229d7 to 3d95543 Compare November 26, 2023 16:30
ubuntu:16.04 version of libcurl doesn't have the mime feature compiled in
@sagebind
Copy link
Collaborator

We support linking against libcurl versions older than 7.56.0 (when the mime API was added) so this will need to be behind an opt-in feature to avoid breaking compatibility with those older versions.

@@ -11,6 +11,7 @@ mod form;
mod handle;
mod handler;
mod list;
mod mime;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mime is kinda its own API that isn't specific to the easy API, so I would make mime a top-level module.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can see what you're saying about "kinda its own API".
However, mime API doesn't have a meaning without the easy API, quite similar to the form API. So basically, I've put the mime module in the same level as the form module.

I don't mind extracting it, just thought it is worth double checking this before doing so.

Your call though, I'll do what you ask :)

@@ -378,6 +379,8 @@ pub fn ssl_ctx(cx: *mut c_void) -> Result<(), Error> {
/// ```
pub struct Easy2<H> {
inner: Box<Inner<H>>,
/// Mime handles to free upon drop
mimes: Vec<*mut curl_sys::curl_mime>,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only one mime object should be attached to an easy handle at a time since CURLOPT_MIMEPOST replaces any previously assigned mime, so this doesn't seem like it needs to be a Vec.

This should also probably go inside Inner like everything else.

I would also prefer to avoid a raw pointer here since that requires multiple implementations handling the calling of curl_mime_free in multiple places. I wonder if there is a way of keeping the drop code in the Mime struct?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. Done.

 - The raw mime handle is now wrapped by a rust struct which will call curl_mime_free() upon Drop
 - Easy2 now keeps the MimeHandle as an Option instead of Vec
 - The above Option is kept inside Inner instead of directly under Easy2
@tsnoam
Copy link
Author

tsnoam commented Nov 27, 2023

We support linking against libcurl versions older than 7.56.0 (when the mime API was added) so this will need to be behind an opt-in feature to avoid breaking compatibility with those older versions.

Ok. Done.

@tsnoam
Copy link
Author

tsnoam commented Nov 30, 2023

@sagebind
I've adhered to your comments (except for the one I replied with a question of my own).
Is there anything else you would to see?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants