I'm implementing an integration to an API and according to example in the documentation I need to post a file using -T/--upload-file.
curl -u "username:password" -0 –X POST -T filename.txt -H "Content-Type: text/plain" "http://url"
My solution:
$fp = fopen('/home/myFile.txt', 'rb');
curl_setopt($ch, CURLOPT_INFILE, $fp);
curl_setopt($ch, CURLOPT_INFILESIZE, filesize('/home/myFile.txt'));
The problem however is that CURLOPT_INLINE only works when using PUT, whereas the example is using POST.
I've seen the following solution but I don't think that's what I'm supposed to use since it doesn't seem to be the same thing as -T. I don't see any mention of key name in the documentation either.
curl_setopt($c, CURLOPT_POST, true);
curl_setopt($c, CURLOPT_POSTFIELDS, array('file'=>'#/home/myFile.pdf'));
Is there a way to do this properly?
If you add --libcurl code.c to your curl command line you'll see exactly which libcurl options it used, and then you'll see that CURLOPT_CUSTOMREQUEST is what you miss in your solution to emulate that command line. Ie the CURLOPT_INFILE approach will assume and default to PUT, but you can override that.
Related
I have the following bash curl command which returns the api results i want
curl -v -H 'Accept-Encoding:gzip,deflate,sdch' http://api.blabla.com?search_id=my_id --compressed
I am writing a PHP sdk for this API but i can not convert this curl command into php curl.
This is what i have tried so far:
curl_setopt($ch1, CURLOPT_URL, $resultsURL);
curl_setopt($ch1, CURLOPT_HTTPHEADER, 'Connection: Keep-Alive');
curl_setopt($ch1, CURLOPT_ENCODING, 'gzip,deflate');
curl_setopt($ch1, CURLOPT_CONNECTTIMEOUT, 0);
curl_setopt($ch1, CURLOPT_TIMEOUT, 15); // number of seconds to allow curl to execute
$results = curl_exec($ch1);
echo(json_encode($results));
curl_close($ch1);
I get some results but they are inconsistent. The usual response is around 9MB of json (from the cli curl) and i get everything from 1.46KB to 900KB. All this happen on the same api call...
What can be wrong with this code or how can i get this done? I am out of ideas about it
Edit: after a long debug i found out that bash curl and php curl send the same request and it must be the servers (apache in my case) fault that it doesnt fetch everything back to me in the response.
I will edit again and post an answer when i find exaclty what it is.
php curl manual says for CURLOPT_ENCODING
The contents of the "Accept-Encoding: " header. This enables decoding
of the response. Supported encodings are "identity", "deflate", and
"gzip". If an empty string, "", is set, a header containing all
supported encoding types is sent.
So use empty there to support any encoding.
curl_setopt($ch1, CURLOPT_ENCODING, '');
I'm trying to post to a file service with CDN translating the cli -T option to PHP code, but I don't really know what the equivalent is, or what is the corresponding code that would replicate it. I've seen a options around CURLOPT_HTTPHEADER, but that doesn't seem to work in correspondence to other headers.
The exact thing I'm trying to replicate is this:
curl -XPUT -T "test.png" -v -H "X-Auth-Token:MYTOKEN" -H"Content-Type: text/plain" "https://somecdn.com"
I think it's something like this, but I'm unsure:
$ch = curl_init();
// Set up the options
curl_setopt($ch, CURLOPT_URL, "https://mycdn.com/test.txt");
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
"X-Auth-Token: mytoken",
"Content-type: text/plain"
)
);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, array("file" => "#test.txt") );
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($ch);
$info = curl_getinfo($ch);
curl_close($ch);
I'm surprised, I suppose, that -T flag doesn't have a similar curl_setopt.
So the precise question is this:
What is the proper way to replicate cURL CLI -T "test.png" in PHP?
Take into consideration as PHP 5.5 uploading file this way (#filename) is deprecated.
Also, PHP 5.5 introduces a new option/flag regarding upload process, called by CURLOPT_SAFE_UPLOAD:
TRUE to disable support for the # prefix for uploading files in
CURLOPT_POSTFIELDS, which means that values starting with # can be
safely passed as fields. CURLFile may be used for uploads instead.
Added in PHP 5.5.0 with FALSE as the default value. PHP 5.6.0 changes
the default value to TRUE.
So if you've PHP 5.5+ you must set CURLOPT_SAFE_UPLOAD (though 5.5 is false by default) to false:
curl_setopt($ch, CURLOPT_SAFE_UPLOAD, false);
Another option is using the CURLFile class.
And remember: Filename MUST be absolute path.
I wish to issue the following curl request using php-curl:
curl "http://www.example.com/" -F "file=#foo.ext"
How do I need to set this up in PHP (using curl_init, _setopt, etc.), assuming foo.ext lives on the machine from which I'm issuing the request?
you'd use
curl_setopt($curl_handle, CURLOPT_POST, TRUE);
curl_setopt($curl_handle, CURLOPT_POSTFIELDS, array('file' => '#foo.ext'));
plus whatever options you need. Relevant docs here: http://php.net/curl_setopt
UPDATED THANKS TO ANSWERS:
Can someone point out the difference between:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $api_root);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, "xml"); // tried http_build_query also
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // Added this, still no good
return curl_exec($ch); // returns false
and:
$curl = "curl -X POST -d 'xml' {$api_root}";
return `$curl`; // returns expected xml from server
AND/OR
More generally, are there any good breakdowns out there for conversion/reference between php's libcurl default values/headers and those of curl on the command line?
I know this is almost a dupe of curl CLI to curl PHP and CLI CURL -> PHP CURL but I'm hoping for something more definitive.
When you use backticks then PHP invokes a shell. This can be dangerous, especially when you include variables in the command. If someone has a way to influence the value of $api_root they would be able to invoke any command on your system.
Using the API is much safer and probably faster as well as the curl libraries are loaded into PHP.
As for why it's not working it seems others have answered that question :)
curl_exec returns true or false by default. You need to specify CURLOPT_RETURNTRANSFER:
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
Since curl_exec is returning false (not NULL as indicated in the original question), try using curl_error() to determine why it's returning false.
TFM (read it): curl_exec(), curl_setopt()
Edit for posterity's sake:
The OP discovered that an SSL issue was the hindrance. The both libcurl (as called through PHP) and the curl command-line do SSL peer verification for every transaction, unless the user explicitly disables it.
The likely scenario is that the shell environment is using a different CA bundle than PHP's libcurl implementation. To remedy this, set CURLOPT_CAINFO to be the same as the shell's CURL_CA_BUNDLE environment variable and then peer verification should work.
#OP: I'd be curious to know if the above suggestion is confirmed working in your case, or if there is something else different with the SSL configuration.
in your php example you are missing
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
from php manual:
curl_exec
Returns TRUE on success or FALSE on failure. However, if the CURLOPT_RETURNTRANSFER option is set, it will return the result on success, FALSE on failure.
Add this line:
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
To match the CLI version:
$curl = "curl -X POST -d 'xml' {$api_root}";
return `$curl`; // returns expected xml from server
I also needed:
// Thanks to all the answers
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// This appears to default false on CLI, true in libcurl
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
When using the PHP curl functions, is there anyway to see the exact raw headers that curl is sending to the server?
You can use curl_getinfo:
Before the call
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
After
$headers = curl_getinfo($ch, CURLINFO_HEADER_OUT);
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://www.example.com/");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
curl_exec($ch);
var_dump(curl_getinfo($ch,CURLINFO_HEADER_OUT));
?>
Only available in php 5.1.3
http://php.net/manual/en/function.curl-getinfo.php
You can verify that they are the same by using your console and hitting
curl http://example.com/ -I
or
curl --trace-ascii /file.txt http://example.com/
AFAIK, the PHP/CURL binding still lacks proper support for CURLOPT_DEBUGFUNCTION which is a callback from libcurl that can provide all those details.
That's the primary reason why I recommend people to work out HTTP scripting things with the curl command line tool and its --trace-ascii option FIRST, then translate that into a PHP function.
be sure to set the CURLINFO_HEADER_OUT option before making the curl_getinfo call
curl_setopt($c, CURLINFO_HEADER_OUT, true);