0

I have a hosted server with curl installed, but not http_post_data() pecl.

I'm trying to translate this (working) http_post_data() code to curl:

$responseString = @http_post_data("http://" . $this->username . ":" . $this->password ."@" . $this->webserviceHost . $this->requestUriBase .$request,
    $requestString,
    array('http_auth' => $this->username . ":" . $this->password, 'headers' => array('Content-Type' => 'text/xml')));

I've tried:

$url = "http://" . $this->username . ":" . $this->password ."@" . $this->webserviceHost . $this->requestUriBase .$request;
        curl_setopt($this->curl, CURLOPT_HTTPHEADER, array('Accept: application/xml', 'Content-Type: application/xml'));
        curl_setopt($this->curl, CURLOPT_URL, $url);
        curl_setopt($this->curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
        curl_setopt(CURLOPT_USERPWD, "[$this->username]:[$this->password]");
        curl_setopt ($this->curl, CURLOPT_POST, true);
        curl_setopt ($this->curl, CURLOPT_POSTFIELDS, array($requestString));
        $content = curl_exec($this->curl);  

... and failed: couldn't connect to host

What's the correct code?

shredding
  • 5,374
  • 3
  • 46
  • 77
  • for testing, simplify it and just do a request to the page with CURLOPT_RETURNTRANSFER and see if you're at least getting that far. – TecBrat Mar 12 '12 at 10:26
  • I added CURLOPT_RETURNTRANSFER (thats why I get the "couldn't connect to host"), or what do you mean by simplify? – shredding Mar 12 '12 at 10:30
  • `curl_setopt` has a return value. If it is `FALSE` the setting failed. You should check if all of your settings work by checking the return value. – hakre Mar 12 '12 at 10:40
  • Thank you. This one fails, I guess there's a missing key. Do you know why? http_post_data does not require a key. curl_setopt ($this->curl, CURLOPT_POSTFIELDS, array($requestString)); – shredding Mar 12 '12 at 10:45
  • Ah that's what I assumed in my answer below as well. See there for a hint. – hakre Mar 12 '12 at 10:47
  • Thank you. I'm consuming a non-documented alfresco api. So, how can I know the key? How does this work in http_post_data() without the key? – shredding Mar 12 '12 at 10:51

4 Answers4

2

Here is a function that should allow you to use your existing code unmodified:

if (!function_exists('http_post_data')) {
  function http_post_data ($url, $data, $options) {

    // Construct the URL with the auth stripped out
    $urlParts = parse_url($url);
    $urlToUse = $urlParts['scheme'].'://'.$urlParts['host'];
    if (isset($urlParts['port'])) $urlToUse .= ':'.$urlParts['port'];
    $urlToUse .= $urlParts['path'];
    if (isset($urlParts['query'])) $urlToUse .= '?'.$urlParts['query'];

    // Convert headers to a format cURL will like
    $headers = array();
    if (isset($options['headers'])) {
      foreach ($options['headers'] as $name => $val) {
        $headers[] = "$name: $val";
      }
    }

    // Initialise cURL with the modified URL
    $ch = curl_init($urlToUse);

    // We want the function to return the response as a string
    curl_setopt ($ch, CURLOPT_RETURNTRANSFER, TRUE);

    // Set the method to POST and set the body data
    curl_setopt ($ch, CURLOPT_POST, TRUE);
    curl_setopt ($ch, CURLOPT_POSTFIELDS, $data); // Wrapping this in an array() is definitely wrong, given that the content-type is xml

    // Set the auth details if specified
    if (isset($urlParts['user'], $urlParts['pass'])) {
      curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY); // It's probably best to allow any auth method, unless you know the server ONLY supports basic
      curl_setopt($ch, CURLOPT_USERPWD, $urlParts['user'].':'.$urlParts['pass']); // The square brackets are not required and will be treated as part of the username/password
    }

    // Set any extra headers
    if ($headers) {
      curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    }

    // Send the request and return the result:
    $result = curl_exec($ch);
    curl_close($ch);
    return $result;

  }
}

This function only implements that options for http_post_data() that you have made use of in your original code - it would be possible to implement other features using cURL as well, but I have not bloated the above code with unnecessary implementations of them. If does not do much error checking, particularly in terms of validating the supplied URL, so you may wish to add some additional sanitization.

This function is wrapped in an if (!function_exists()) to allow you to place it your code and be distributed anywhere. It will not collide with the native function where it is available.

DaveRandom
  • 87,921
  • 11
  • 154
  • 174
  • First of all I want to thank everyone for there effort. Since your function returns false, I'm starting to think that my server may be blocked by a firewall or something like that. Is it possible to test this? – shredding Mar 12 '12 at 11:04
  • It would be useful to see the error messages, you should make sure your remove any `@` from the function call suppressing the errors, and turn error reporting up to max (`ini_set('display_errors', 1); error_reporting(E_STRICT | E_ALL);`) Also see what `curl_error($ch);` shows you, and adding the output of `print_r(curl_getinfo($ch));` to the question might be helpful... – DaveRandom Mar 12 '12 at 11:07
  • Thank you, this does work now: I've gained access to the original server and the script worked there. Thus, I'm assuming a firewall. All of you helped me very much. – shredding Mar 12 '12 at 11:43
1

To configure and execute a CURL request, I suggest the following format:

    # in curl URL is scheme://hostname/rest, and hostname != authority
    #     (authority is hostname plus port and with user/pass in front)

    $url = sprintf('http://%s/%s', $this->webserviceHost
                    , $this->requestUriBase . $request);
    $options = array(
         CURLOPT_HTTPHEADER     => array(
             'Accept: application/xml', 
             'Content-Type: application/xml',
         ),
         CURLOPT_HTTPAUTH       => CURLAUTH_BASIC,
         # don't use the brackets []
         CURLOPT_USERPWD        => $this->username . ':' . $this->password,
         CURLOPT_POST           => TRUE,
         CURLOPT_POSTFIELDS     => $requestString,
         CURLOPT_RETURNTRANSFER => TRUE,
    );

    $this->curl = curl_init($url);
    $r = curl_ setopt_ array($this->curl, $options);
    if (!$r) throw new Exception('Failed to setup options.');
    $content = curl_exec($this->curl); # This needs CURLOPT_RETURNTRANSFER => TRUE

I'm not sure about CURLOPT_POSTFIELDS because you don't have specified what $requestString contains. It's likely that this setting above is wrong. See curl POST format for CURLOPT_POSTFIELDS.

Edit: You have specified it via http_post_data:

String containing the pre-encoded post data

Curl supports that as well, just don't pass as array, pass it as string:

     CURLOPT_POSTFIELDS     => $requestString,
Community
  • 1
  • 1
hakre
  • 193,403
  • 52
  • 435
  • 836
  • Thank you, this does work now: I've gained access to the original server and the script worked there. Thus, I'm assuming a firewall. All of you helped me very much. – shredding Mar 12 '12 at 11:43
0

Try removing username and password from the URL and use CURLOPT_USERPWD without brackets:

curl_setopt(CURLOPT_USERPWD, "$this->username:$this->password");
Gergo Erdosi
  • 40,904
  • 21
  • 118
  • 94
  • Thank you very much for helping. Unfortunately, this code (with added reference to curl as 1st param) does not work either. – shredding Mar 12 '12 at 10:31
0

your URL is not supposed to contain the username and password - when you do that, curl interprets it to be part of the hostname.

Hence the error "couldn't connect to host".

you're already doing the needful by including the authentication information by setting the USERPWD option.

jrharshath
  • 25,975
  • 33
  • 97
  • 127
  • I've tested that, and it does not work :( $url = "http://" . $this->webserviceHost . $this->requestUriBase .$request; – shredding Mar 12 '12 at 10:33