alexcrichton / curl-rust

Rust bindings to libcurl
MIT License
1.02k stars 233 forks source link

data in local stack lost outside write_function after post performed #366

Closed jonghne closed 3 years ago

jonghne commented 3 years ago

my codes as follows:

fn mypost(url: &str, data: &str) {
    let mut cache = String::new();
    let mut handle = Easy::new();
    handle.url(url).unwrap();
    handle.post(true).unwrap();
    handle.post_field_size(data.len() as u64).unwrap();
    let mut list = List::new();
    list.append("Content-Type:application/json").unwrap();
    handle.http_headers(list).unwrap();
    {
        let mut transfer = handle.transfer();
        transfer.read_function(|buf| {
            Ok(data.as_bytes().read(buf).unwrap_or(0))
        }).unwrap();

        transfer.write_function(|data| {
            cache = String::from_utf8_lossy(data).to_string();
            println!("in closure: {}", cache.len());
            Ok(data.len())
        }).unwrap();
        transfer.perform().unwrap();
    }
    println!("again {}", cache.len());
}

when I tested post, and checked the result print: the cache length in closure is bigger than outside. the response body length is about 1024bytes. if print the contents in cache, I found I lost the data from the beginning to some random position. Why? waiting for your reply, thank you.

jonghne commented 3 years ago

curl version is "0.4.34".

alexcrichton commented 3 years ago

Thanks for the report! I think the issue here though is that write_function can be called multiple times? You only store one value of the closure instead of concatenating everything?

sagebind commented 3 years ago

Yeah, your write_function will be called multiple times with the response buffer in pieces. Try something like this (untested):

        transfer.write_function(|data| {
            cache += String::from_utf8_lossy(data);
            println!("in closure: {}", cache.len());
            Ok(data.len())
        }).unwrap();
sagebind commented 3 years ago

Closing since I believe this question has been answered. If not, feel free to reopen!