title: libcurl retrieve response from HTTP request
body: <p>In my OS X application, I've been using NSURLRequest for quite a while to send an HTTP request to a server and receive the response.
  Now I need to migrate this code to use libcurl instead to be able to run it on Windows and Mac.</p>
  
  <p>For some reason, I can't get it to work...</p>
  
  <p>Here's what I'm trying to do:</p>
  
  <ul>
  <li>sending a block to the server using HTTP post</li>
  <li>Server evaluates block and sends response back</li>
  <li>receiving response, evaluating, proceeding ...</li>
  </ul>
  
  <p>When the block that is sent along with the request is valid, an "application/octet-stream" data block is sent back to the requesting application right after. If the file is not valid, a return code 403 is returned.</p>
  
  <p>When I try to put the post request URL and the data block directly in the browser, it works.
  If the data block is valid, a file will be downloaded, if not: a 403 page is shown.</p>
  
  <p>My libcurl code looks like this:</p>
  
  <pre><code>curl_global_init(CURL_GLOBAL_ALL);
  curl = curl_easy_init();
  
  if (curl)
  {
      struct url_data data;
      data.size = 0;
      data.data = (char*) malloc(4096); /* reasonable size initial buffer */
  
      if(NULL == data.data)
      {
          fprintf(stderr, "Failed to allocate memory.\n");
          return NULL;
      }
  
      curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
      curl_easy_setopt(curl, CURLOPT_URL, "&lt;my-url&gt;");
      curl_easy_setopt(curl, CURLOPT_POSTFIELDS, [postData cStringUsingEncoding:NSASCIIStringEncoding]);
  
      curl_slist_append(headerlist, "Content-Type: application/x-www-form-urlencoded");
      curl_slist_append(headerlist, [length cStringUsingEncoding:NSASCIIStringEncoding]);
  
      curl_easy_setopt(curl, CURLOPT_HEADER, headerlist);
  
      curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
      curl_easy_setopt(curl, CURLOPT_WRITEDATA, &amp;data);
  
      curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcurl-agent/1.0");
  
      res = curl_easy_perform(curl);
  
      if(res != CURLE_OK)
      {
          fprintf(stderr, "curl_easy_perform() failed: %s\n",
                           curl_easy_strerror(res));
      }
  
      curl_easy_cleanup(curl);
      }
      curl_global_cleanup();
  }
  </code></pre>
  
  <p>And my write function looks like this:</p>
  
  <pre><code>struct url_data 
  {
      size_t size;
      char* data;
  };
  
  size_t write_data(void *ptr, size_t size, size_t nmemb, struct url_data *data)
  {
      size_t index = data-&gt;size;
      size_t n = (size * nmemb);
      char* tmp;
  
      data-&gt;size += (size * nmemb);
  
      fprintf(stderr, "data at %p size=%ld nmemb=%ld\n", ptr, size, nmemb);
      tmp = (char*) realloc(data-&gt;data, data-&gt;size + 1); /* +1 for '\0' */
  
      memcpy((data-&gt;data + index), ptr, n);
      data-&gt;data[data-&gt;size] = '\0';
  
      return size * nmemb;
  }
  </code></pre>
  
  <p>I am receiving the right return codes and also the 403 page in case the block is not valid. In case it's valid, I'm not receiving the response block. The write function is never being called. The connection is always closed immediately.</p>
  
  <p>Can anyone tell me what I'm doing wrong?</p>
  
  <p>Here's a part of the log output of libcurl:</p>
  
  <pre><code>* Adding handle: conn: 0x2a9ee00
  * Adding handle: send: 0
  * Adding handle: recv: 0
  * Curl_addHandleToPipeline: length: 1
  * - Conn 0 (0x2a9ee00) send_pipe: 1, recv_pipe: 0
  * About to connect() to &lt;my-url&gt; port 80 (#0)
  *   Trying &lt;my-url-ip&gt;...
  * Connected to &lt;my-url&gt; (&lt;my-url-ip&gt;) port 80 (#0)
  </code></pre>
  
  <p>Does this <em>recv-pipe</em> cause the problem maybe?
  Should it be 1?</p>
  
  <p>I'm curious to hear your thoughts! Thanks in advance!</p>