76

I'm trying to debug a curl request to a webservice 'getToken' endpoint.

I'm not 100% confident that the URL and the auth info is getting written in to the curl handle correctly.

I'm trying to use curl_getinfo($ch, CURLINFO_HEADER_OUT); to capture the sent request, but it doesn't give me much info. Is there a way to get more in depth diagnostics about what the actual curl request looks like?

Here's the code:

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, "$username:$password");       
curl_setopt($ch, CURLOPT_HEADER, 1); // just getting header to see if we got an auth token
curl_setopt($ch, CURLOPT_FILE, $fh);
curl_setopt($ch, CURLOPT_NOBODY, 1); 
curl_setopt($ch, CURLINFO_HEADER_OUT, 1); // capture the header info
curl_setopt($ch, CURLOPT_VERBOSE, 1); // turn verbose on    
// execute the curl request 

$rh = fopen("request.txt", "w"); // open request file handle
$verbose = fopen('php://temp', 'rw+');
curl_setopt($ch, CURLOPT_STDERR, $verbose);

curl_exec($ch); // execute request

$sent_request = curl_getinfo($ch, CURLINFO_HEADER_OUT);
fwrite($rh, $sent_request); // save the request info
fclose($rh);
!rewind($verbose);
$verboseLog = stream_get_contents($verbose);

echo "Verbose information:\n<pre>", htmlspecialchars($verboseLog), "</pre>\n";

This all works as far as it goes, but returns a 401 every time-- the API admin assures me that the username / pass I have is correct.

I was wondering if I'm somehow getting the URL value wrong, or not sending the right username / pass, but this info isn't printed in the request data saved:

HEAD /export/auth HTTP/1.1
Authorization: Basic Y2FpcmRzdW5mYTpENWlAaVM4cw==
Host: webservices.mycompany.com
Accept: */*

You can see that the username/pass is not recorded (I assume for security). The endpoint URL I think is the host value plus the start of the HEAD value, so webservices.mycompany.com/export/auth?

The "Verbose Information" statement prints nothing. Not sure why on this either!

Thanks for help.

EDIT: added verbose mode from Php - Debugging Curl thanks to commenter immulatin

Community
  • 1
  • 1
user101289
  • 9,888
  • 15
  • 81
  • 148
  • You can set verbose to true: http://stackoverflow.com/questions/3757071/php-debugging-curl – immulatin Jun 13 '13 at 16:49
  • First thing I would check is I'd make a much more simple request with minimum parameters and typed all my variables values manually (url, login, password). Wired errors like that are usually caused by malformed input such as extra spaces etc. – Ranty Nov 11 '13 at 15:42
  • I think this old post could be useful – nik.longstone Apr 28 '14 at 12:44

4 Answers4

107

If you set CURLINFO_HEADER_OUT to true, outgoing headers are available in the array returned by curl_getinfo(), under request_header key:

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://foo.com/bar");
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, "someusername:secretpassword");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);

curl_exec($ch);

$info = curl_getinfo($ch);
print_r($info['request_header']);

This will print:

GET /bar HTTP/1.1
Authorization: Basic c29tZXVzZXJuYW1lOnNlY3JldHBhc3N3b3Jk
Host: foo.com
Accept: */*

Note the auth details are base64-encoded:

echo base64_decode('c29tZXVzZXJuYW1lOnNlY3JldHBhc3N3b3Jk');
// prints: someusername:secretpassword

Also note that username and password need to be percent-encoded to escape any URL reserved characters (/, ?, &, : and so on) they might contain:

curl_setopt($ch, CURLOPT_USERPWD, urlencode($username).':'.urlencode($password));
lafor
  • 12,472
  • 4
  • 32
  • 35
6

curl_getinfo() must be added before closing the curl handler

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://example.com/bar");
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, "someusername:secretpassword");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
curl_exec($ch);
$info = curl_getinfo($ch);
print_r($info['request_header']);
curl_close($ch);
AdrienW
  • 3,092
  • 6
  • 29
  • 59
soulge
  • 89
  • 1
  • 3
4

You can also use a proxy tool like Charles to capture the outgoing request headers, data, etc. by passing the proxy details through CURLOPT_PROXY to your curl_setopt_array method.

For example:

$proxy = '127.0.0.1:8888';
$opt = array (
    CURLOPT_URL => "http://www.example.com",
    CURLOPT_PROXY => $proxy,
    CURLOPT_POST => true,
    CURLOPT_VERBOSE => true,
    );

$ch = curl_init();
curl_setopt_array($ch, $opt);
curl_exec($ch);
curl_close($ch);
acetone
  • 156
  • 1
  • 3
  • 8
2

The request is printed in a request.txt with details

$ch = curl_init();
$f = fopen('request.txt', 'w');
curl_setopt_array($ch, array(
CURLOPT_URL            => $url, 
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_FOLLOWLOCATION => 1,
CURLOPT_VERBOSE        => 1,
CURLOPT_STDERR         => $f,
));
$response = curl_exec($ch);
fclose($f);
curl_close($ch);

You can also use curl_getinfo() function.