Using ofxCurl

Hi

Post aimed at Roxlu, but anyone else can make suggestions if they know :slight_smile: Also good to keep here for the archive.

I decided to revisit libcurl instead of Poco for http stuff due to previous Windows thread crashes. I noticed your ofxCurl is a long way on from what I started playing with a year ago

https://github.com/roxlu/ofxCurl

I am trying to get your addon working with Codeblocks Windows. I don’t want/need to compile libcurl, unless its not the right version to use in your addon? (i mean, youve not included mac only or something?)

Anyway, I have so far:

  1. included files from here in my project
    \openframeworks\v0.062\addons\ofxCurl\src\
    \openframeworks\v0.062\addons\ofxCurl\src\include_codeblocks\

  1. added the search path

  1. added preprocessor defines, i think this is right …

  1. added to the top of ofxCurl.h

#define CURL_STATICLIB
#define CURL_DISABLE_LDAP

as in your readme it says:

In Code::Blocks I had to define these two defines to make it
link:

CURL_STATICLIB
CURL_DISABLE_LDAP

So, when I go to build, I get the error:

C:\openframeworks\v0.062\addons\ofxCurl\src\ofxCurlFileDownload.cpp||In member function ‘bool ofxCurlFileDownload::startDownloading()’:

C:\openframeworks\v0.062\addons\ofxCurl\src\ofxCurlFileDownload.cpp|69|error: ‘assert’ was not declared in this scope

Any ideas what is going wrong?

Many thanks!

I don’t know the code but as far as I know about macros like this, you can try to just comment the line out, because assert commands are only for debugging (or at least should only be used for that, not for programming logic)

maybe this helps

thanks :slight_smile:

Roxlu perhaps you can say if its needed here…

  
  
// we use the multi handles because of async-io  
multi_curl_handle = curl_multi_init();  
//assert(multi_curl_handle!=NULL);  
CURLMcode t = curl_multi_add_handle(multi_curl_handle, curl_handle);  
  

  
  
ofxCurlForm* form = curl.createForm("myscript.php");  
form->addInput("testvar","10");  
form->post();  
  

That seems to work, I can see that the script is showing its output in the console window. How can I read this output though, is it stored anywhere?

Also, is ofxCurl thread safe?

Thanks!

Regarding the assert: It’s used as a safety line, for checking things to make functions safer. In your example, it’s used to make sure that the creation of multi_curl_handle was successful before proceeding. So you don’t “need” them, but then you don’t know when something is wrong (e.g. unsuccessful pointer creation because out-of-memory, or other things), and the code could start to behave unpredictably.
Adding #include or #include assert.h in ofxCurlFileDownload.h should make the error go away, although I don’t know why it appeared in the first place - Roxlu would also be affected by this, but obviously is not.

Ok, I am trying to update ofxCurl to handle errors, return responses from forms and get a url.

On the errors, right now an app will crash if you try to post a form and your internet is turned off.

In ofxCurlForm::post I uncommented this line
curl_easy_setopt(easy_handle, CURLOPT_VERBOSE, CURLOPT_STDERR);

this prints to the console debug info from curl.

When trying to post with the internet turned off, the app crashes, and the console debug from curl says:

Could not resolve host: [url]; No data record of requested type
Closing connection #0

After the curl form post and cleanup, it has this, but its obviously not working

  
  
	else if(result == CURLE_COULDNT_RESOLVE_HOST) {  
                printf("\n\nwe have an error\n\n");  
		throw ofxCurlException(  
			"Curl cannot resolve host: " +action  
			,OFXCURL_CANT_RESOLVE_HOST  
		);  
	}  
  

[edit]
So it turns out it is catching the error, but the ofxCurlException is whats making it crash, commenting out that line it doesn’t crash.

Any thoughts would be great, thanks.

yeah, it actually _does_ work - it throws an exception. You’d have to catch it appropriately, before it gets caught by the main program and shuts down your process.
See http://www.learncpp.com/cpp-tutorial/712-handling-errors-assert-cerr-exit-and-exceptions/ and http://www.learncpp.com/cpp-tutorial/151-the-need-for-exceptions/ and following for an introduction.

I appreciate that, but I’m just a little unsure how to catch the error in this example. So the code looks like this:

  
  
result = curl_easy_perform(easy_handle);  
  
// free list..  
curl_easy_cleanup(easy_handle);  
curl_formfree(post_curr);  
  
// throw exceptions.  
if(result == CURLE_OPERATION_TIMEOUTED) {  
throw ofxCurlException(  
"Curl timed out"  
,OFXCURL_TIMEOUT  
);  
}  
else if(result == CURLE_COULDNT_RESOLVE_HOST) {  
throw ofxCurlException(  
"Curl cannot resolve host: " +action  
,OFXCURL_CANT_RESOLVE_HOST  
);  
}  
  

when it does throw, it creates a new ofxCurlExecption object. Can this be read from caught from anywhere, or just inside this ofxCurlForm class?

There is no try{} catch{} in this class.

I’ve changed the code to this…

  
  
try{  
            result = curl_easy_perform( easy_handle );  
  
                // throw exceptions.  
                if(result == CURLE_OPERATION_TIMEOUTED) {  
                    throw ofxCurlException("Curl timed out", OFXCURL_TIMEOUT );  
                }  
                else if(result == CURLE_COULDNT_RESOLVE_HOST) {  
                    throw ofxCurlException("Curl cannot resolve host: " +action,OFXCURL_CANT_RESOLVE_HOST);  
                }  
        }  
        catch(...){  
            printf("caught\n");  
        }  
  

Obviously it doesn’t catch the ofxCurlException object, but the app doesn’t crash now and shows ‘caught’ in console.

How do I catch the exception outside of this class and do I need to try{} it?

Thanks

you can catch exceptions from the calling function’s scope, too… thrown exceptions travel up the calling hierarchy until they encounter a catch (stack unwinding, read http://www.learncpp.com/cpp-tutorial/153-exceptions-functions-and-stack-unwinding/)
you’ll need a try block somewhere in the hierarchy, but not necessarily in the function where you throw the exception.

I updated the git version. It contains an example on how to post a simple form with some input fields and a file element. I added a function to retrieve the response from the server after posting. See the getPostResponseAsString and getPostResponseAsBuffer.

Both functions return the same data though getPostResponseAsBuffer returns a std::vector which can be handy if you want to parse the result.

Link to the examples:
https://github.com/roxlu/ofxCurl/blob/master/example/ofxcurl-upload-file-and-handle-response/testApp.cpp

Chris, let me know if this works for you!

Greetz!
roxlu

i was hoping you guys would be able to tell me how to make this GET request:

curl -X POST -d “{“username”:“name”, “devicetype”:“someThing”}”

i tried it this way:

  
  
  
ofxCurlForm* form = curl.createForm("[http://10.0.1.145/api"](http://10.0.1.145/api"));  
string q = "{\"username\":\"stephanS\", \"devicetype\":\"myTestApp01\"}";  
form->addInput(q,q);  
form->post();  
  

but the response says: [{“error”:{“type”:2,“address”:"/",“description”:“body contains invalid json”}}]

it am trying to talk to the philips hue bridge.
Someone in the hue hacking forum said the problem was
“submitting the data as form data instead of the request body.”

So how would i use ofxcurl to submit something not as form ?
thx,
stephan.

i ended up call shell commands directly from inside OF.
Like so:

char command[] = “curl -X POST http://10.0.1.145/api -d ‘{“username”:“zxasqweqwef”, “devicetype”:“abc”}’” ;
int status = system( command );

1 Like

hey @stephanschulz How did you get the answer from the server?

ok. easy:

std::string cmd = "curl -v -X POST -d '{\"author\": \"alanisawesome\",\"title\": \"The Turing Machine\"}' 'https://xxxxxx.firebaseio.com/object.json'";
string reply = ofSystem(cmd);
std::cout << "==" << endl << reply << endl << "==" << std::endl;
1 Like