Curl use with post

Hi,

I want to test a API with the curl crate.
I discover Easy2 with Handler to do that.
A example is done here in documentation : Handler in curl::easy - Rust

I want to use post request. We need to implement this traits :

fn read(&mut self, data: &mut [u8]) -> Result<usize, ReadError> 

I guess the json data I want to pass must be set in data: &mut [u8] .
Maybe a str in bytes format...
This does not works. I am not really sure to implement read as needed.

Can you help me please ? I read documentation but, sometimes example are very helpful...

This is my simple code :

mod tests {
    use curl::easy::{Easy2, Handler, WriteError, ReadError};

    #[test]
    fn curl_test(){
        #[derive(Debug)]
        struct Collector(Vec<u8>);

        impl Handler for Collector {
            fn write(&mut self, data: &[u8]) -> Result<usize, WriteError> {
                self.0.extend_from_slice(data);
                Ok(data.len())
            }

            fn read(&mut self, data: &mut [u8]) -> Result<usize, ReadError> {
                data = "-H 'Content-Type: application/json; charset=utf-8' {name:\"NAME\"}".as_bytes();
                Ok(data.len())
            }
        }

        let mut easy = Easy2::new(Collector(Vec::new()));
        easy.post(true).unwrap();
        easy.url("http://localhost:8080/add-name").unwrap();
        easy.perform().unwrap();

        assert_eq!(easy.response_code().unwrap(), 200);
        let contents = easy.get_ref();
        println!("{}", String::from_utf8_lossy(&contents.0));
    }
}


This is re-assigning the variable data rather than writing data into the given buffer. Maybe put an std::io::Cursor<Vec<u8>> as extra field in your Collector. This type has a method readwhich has the exact same function signature asHandler::readwith the exception of the error type. You can use.map_err(|_| ReadError::Abort)on the return value ofread` to get the right error type.

read is supposed to read the data I need to pass to post request... ?
I am confused about the way of doing that...

I am looking also reqwest crate aside...

You can put the data you want to send in the Cursor in advance when creating the Collector. Then the read method can read out of this cursor into the buffer provided by curl.

By the way I just noticed that you are trying to pass arbitrary commandline arguments through the read method. That won't work. The data passed in through the read method is sent to the server verbatim. If you want yo set a header you have to call the right method for this on the easy variable before calling perform. I think you can use the http_headers method.

2 Likes

OOOOOOOOOOOOOOOOOh !

I was trying to use reqwest in place or curl crate.
I arrive at the same problem.
I see you answer and now I realize evething.

Thank you very much !

I post my answer with reqwest if it can help other people that are looking for the same example...
I use less code for the same thing.

let client = reqwest::blocking::Client::new();
let res = client.post("http://localhost:8080/add")
    .header("Content-Type", "application/json; charset=utf-8")
    .body("{ \"name\": \"string\"}") // exact body to send
    .send();

    if let Ok(body) = res {
        eprintln!("body = {:?}", body.text());
    }