[curl] Consuming code doesn't receive any response, but verbose mode shows it in stdout


#1

EDIT: This is now solved, thanks to some quick responding by the kind folks here.

I’m experimenting with the curl crate, and I’m experiencing a weird issue where my Easy instance never actually gets a response.

However, when I set the same Easy instance to verbose mode, I do see the response appearing in stdout. But even then it still won’t appear in the callback given to easy.transfer.write_function().

What am I doing wrong here?


struct Blah { ... }

impl Blah {
    fn get(&mut self, url: &str, headers: &[String]) -> Result<(), CurlErr> {
        let mut easy = Easy::new();
        println!("[GET] url: {}", url);
        easy.url(url)?;
        easy.get(true)?;
        easy.follow_location(true)?;
        easy.autoreferer(true)?;
        // easy.verbose(true)?;
        easy.username("jjpe");

        let mut header_list = curl::easy::List::new();
        for header in headers {
            header_list.append(header)?;
            println!("[header]    {}", header);
        }
        easy.http_headers(header_list)?;

        use std::time;
        easy.timeout(time::Duration::from_secs(10))?;
        easy.perform()?;

        // TODO: Get the response JSON as it has information we want
        let mut transfer = easy.transfer();
        transfer.write_function(|data| {
            // "data!" is never printed
            println!("data!");
            stdout().flush().unwrap();
            Ok(stdout().write(data).unwrap())
        })?;

        Ok(())
    }


    // Convenience methods


    pub fn get_release_by_tag(&mut self, tag: &str) -> Result<(), CurlErr> {
        let url = format!(
            "{}/repos/{}/{}/releases/tags/{}",
            Self::GITHUB_API_URL,
            self.owner,
            self.repo,
            tag
        );
        let headers = [
            format!("Authorization: token {}", self.api_token),
            format!("Accept: application/json"),
            format!("User-Agent: ghdeploy"),
        ];
        self.get(&url, &headers)
    }
}
```

#2

I think you have to set the write_function callback and then call transfer::perform - I don’t think you need to (and probably shouldn’t) call perform on easy itself. As your code is written, the output is just lost because nothing is consuming it on your side.


#3

Indeed @alexcrichton just told me the answer on GitHub.

But calling easy.perform() wasn’t the issue; In fact the examples showed me to do that, and it seems to work fine if you can get away with the 'static lifetime.

The real issue was the easy.perform() call not being the last expression in the function.
Thanks anyway for the help though :slight_smile:


#4

Right, the issue is you’ve not set a callback prior to doing the retrieval. I was also just saying that it’s probably clearer to call perform on the Transfer value. Anyway, you’ve got it sorted so :thumbsup: