PHP cURL sending empty parameters - php
cURL is new to me. I'm trying to integrate an api via PHP cURL. The api that I'm trying to access requires that parameters be sent as key-value pairs, not json. Their example cURL request in their docs is:
curl -i -X POST -d 'api_key=my_api_key' -d
'email=john#doe.com' -d "first_name=Joe" -d "last_name=Doe" -d
"cust_id=cus_401"
https://serviceurl.com/api/create
My code is apparently sending empty parameters to their api.
$service_url = 'https://serviceurl.com/api/create';
$curl = curl_init($service_url);
$email = $this->session->userdata('email');
$postArray = array(
'api_key' => 'my_api_key',
'email' => $email,
);
$curl_post_data = $postArray;
curl_setopt($curl, CURLOPT_POSTFIELDS, $curl_post_data);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_POST, true);
$curl_response = curl_exec($curl);
if ($curl_response === false) {
$info = curl_getinfo($curl);
curl_close($curl);
die('error occured during curl exec. Additioanl info: ' . var_export($info));
}
curl_close($curl);
echo $curl_response;
echo $info;
Any advice would be greatly appreciated.
your curl php code is sending the data in multipart/form-data format, but as evident by their cli invocation example, their api wants the data in application/x-www-form-urlencoded format.
as explained by the curl_setopt docs, when you give CURLOPT_POSTFIELDS an array, it will automatically be encoded to multipart/form-data, if you give it a string, application/x-www-form-urlencoded will automatically be assumed, and is what their curl cli invocation is using.
lucky for you, PHP has a dedicated function for encoding arrays to application/x-www-form-urlencoded format, called http_build_query, thus
curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($curl_post_data)); will fix your issue of apparently sending empty parameters.
also, if there is a problem setting any of your options, curl_setopt will return bool(false), which your code is completely ignoring, and would go unnoticed, you should fix that, consider using an error-catching setopt wrapper, like
function ecurl_setopt ( /*resource*/$ch , int $option , /*mixed*/ $value ):bool{
$ret=curl_setopt($ch,$option,$value);
if($ret!==true){
//option should be obvious by stack trace
throw new RuntimeException ( 'curl_setopt() failed. curl_errno: ' . $ch .'. curl_error: '.curl_error($ch) );
}
return true;
}
Related
php://input empty when sending long JSON via raw POST
I am sending raw JSON POST data with cURL via PHP, and the server receives it correctly when the JSON is not too long. However, it seems to receive an empty body when it's bigger. This is how I get the body from the server: $dataReceived = file_get_contents("php://input"); When I log $dataReceived on the server side, the expected content is in the log when not big, e.g. this: {"products":[],"allProductIds":["898","920","937","947","979","1007","1044","1064","1124","1146","1162","1178","1194","1215","1239","1291","1346","1395","1444","1629","1673","1695","1757","1868","1929","1992","2018","2050","2096","2112","2136","2178","2225","2280","2303","2318","2340","2394","2447","2459","2476","2486","2510","2520","2558","2591","2626","2655","2689","2727","2975","3175","3224","3283","3311","3333","3342","3353","3376","3389","3400","3419","3469","3506","3535","3610","3722","3765","3782","3802","4002","4020","4039","4060","4094","4130","4171","4213","4246","4281","4317","4348","4426","4473","4502","4545","4558","4563","4663","4688","4713","4733","4757","4875","4924","4984","5028","5057","5088","5102","5117","5145","5174","5197","5216","5236","5255","5275","5310","5336","5369","5422","5433","5464","5477","5505","5516","5541","5563","5587","5616","5627","5673","5703","5744","5773","5822","5839","5903","5999","6075","6196","6326","6483","6794","8360","8429","8599","8724","8798","8953","9150","9198","9247","9295","9347","9415","9463","9636","9991","10105","10219","10337","10451","10566","10681","10796","10912","11134","11244","11354","11465","11576","11687","11798","11874","11924","11973","12025","12074","12125","12175","12640","12699","12838","12844","12848","12852","12862","12866","12870","12874","12880","12884","12888","12894","12935","12943","12947","12952","12958","12962","12966","12970","12974","12979","12988","12992","12997","13001","13010","13012","13016","13020","13026","13030","13034","13039","13049","13059","13093","13128","13144","13148","13154","13158","13162","13172","13182","13217","13223","13368","2851","3828","4804"],"brandlyProductIds":["229082","226046","223246","216800","216750","215456","213613","213157","143436","143406","143362","143312","134066","134022","221020","242298","144021","143921","242348","333387","333424","333443","333517","333624","333681","334021","334043","334086","334135","334159","334184","334220","334261","334318","334351","334376","334398","334448","334505","334530","334552","334581","334606","334639","334672","334701","334734","334763","334792","334825","334962","335099","335325","335382","335439","335464","335482","335491","335500","335521","335532","335553","335575","335680","335770","335795","335877","335991","336032","336049","336066","336088","336276","336293","336310","336329","336370","336411","336452","336493","336530","336561","336598","336631","336705","336751","336782","336819","336850","336859","336977","337002","337033","337058","337083","337133","337207","337256","337366","337403","337428","337456","337473","337490","337515","337540","337565","337582","337599","337616","337637","337682","337710","337738","337791","337800","337831","337881","337906","337928","337953","337981","338006","338031","338056","338099","338135","338175","338201","338244","338269","338340","338422","187730","338815","338968","339121","339427","340235","340308","340461","340614","340687","340840","340987","341060","341133","341206","341279","341352","341425","341675","341981","342072","342254","342350","342441","342532","342714","342805","342896","343042","343115","343188","343261","343407","343480","343553","343626","343690","343754","343818","343882","343946","344010","225836","225770","344210","344214","344216","344218","303935","303610","303601","344223","344234","344236","344238","344241","204360","344254","344256","344262","344264","344268","344270","344272","344274","344277","344279","344281","344283","344285","344287","344288","344290","344292","344295","344299","344301","344303","344308","344313","344330","344333","344335","344337","344340","344342","344344","344349","344354","344371","150836","344434"]} But i get an empty $dataReceived for example when the sent JSON is the one in this pastebin https://pastebin.com/p5ZLrxig This is the code i have to send the request, with verbose log protected static function _apiCall(string $url, array $additionalHeaders = [], string $method="GET", string $data=''){ if($method=="POST"){ $curlLog = __DIR__ . '/curl-log.txt'; $f = fopen($curlLog, 'w'); $ch = curl_init($url); curl_setopt($ch, CURLOPT_VERBOSE, true); curl_setopt($ch, CURLOPT_STDERR, $f); curl_setopt($ch, CURLOPT_STDOUT, $f); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $hdr = [ 'Content-Type: application/json', 'Content-Length: ' . strlen($data) ]; foreach($additionalHeaders as $h) $hdr[] = $h; curl_setopt($ch, CURLOPT_HTTPHEADER, $hdr); curl_setopt($ch, CURLOPT_POSTFIELDS, $data ); $info = curl_getinfo($ch); $result = curl_exec($ch); curl_close($ch); fclose($f); mail("myemail#email.com","$url curl info",print_r($info,true) . ", result:$result, curl log: " . file_get_contents("file://$curlLog") . "\r\n, data:$data"); } else { // ... } } This is the log i get in the email for the big JSON: https://pastebin.com/0pYHTk4h Now, can it be an issue with POST size limit, either in PHP or Apache settings? But i doubt so, since the data is just 33Kb Content-Length: 34581 Also, if it was the case, shouldn't we expect the server (Apache + PHP 7.4.x) to return an HTTP error code like HTTP 500? Instead, we have HTTP 100 and HTTP 200. Seems not related to JSON formatting too, again because we'd expect the server to return an error code. One aspect that may be relevant: the called URL (from which i am logging php://input on server side) actually is a custom Wordpress REST API endpoint (that i have created by calling register_rest_route inside a rest_api_init action handler). I am not currently aware of POST size limits or related issues with WP API, i have no idea if the issue can be with WP. Any hints are appreciated!
request.files is empty from php curl request
I am trying to convert this curl request to php. curl -X POST -F "file=#test_img.jpg" "http://127.0.0.1:5000/FileUploading/UploadImage/"test_img.jpg" This request is working correctly with the following flask-RESTful code class UploadImage(Resource): def post(self, fname): file = request.files['file'] if file: # From flask uploading tutorial filename = secure_filename(file.filename) file.save(os.path.join("Images/", filename)) return jsonify({"Path": "Images/" + filename}) else: # return error return {'False'} However, the following php curl request returns error 400 as it seems the request.files parameter is empty. $file_name = "test_img.jpg"; $post_data = array( "file" => "#" . $file_name, "type" => 'image/jpg' ); $ch = curl_init(); debug_to_console(http_build_query($post_data)); $host = "http://127.0.0.1:5000"; $url = $host . "/FileUploading/UploadImage/" . $file_name; debug_to_console($url); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POST, 1); $file_param = 'file=' . $file_name; curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_data)); $headers = array(); $headers[] = "Content-Type: multipart/form-data"; debug_to_console($headers); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); $result = curl_exec($ch); if (curl_errno($ch)) { debug_to_console('Error:' . curl_error($ch)); } curl_close($ch); I don't know what i am doing wrong in this php request
first off, don't try to upload files using the # method, it was deprecated in PHP 5.5, disabled-by-default in PHP 5.6, and completely removed in PHP 7.0.0, in modern PHP, use CURLFile to upload files. also in line 10 you don't urlencode $file_name, that's a bug. and in line 17 you're trying to encode it to application/x-www-form-urlencoded-format (via http_build_query), but the command you're trying to convert is using multipart/form-data-format, when you give CURLOPT_POSTFIELDS a string (as returned by http_build_query), curl will send it as application/x-www-form-urlencoded by default but to make curl send it in multipart/form-data-format (as you want), set CURLOPT_POSTFIELDS to an array, not a string, and curl will send it in multipart/form-data.
sending json via php curl but not getting a response
I am trying to send a json to a url and get a response back. I am creating the json correctly I believe. However when I try to send it via php curl I do not get a response back. The url I am sending it to does populate a response though. Here is the php: <?php $post = array("prompt" => $question, "functionName" => $func_name, "argumentNames" => $argumentNames, "testCases" => $testCases); $transfer = json_encode($post); $ctrl = curl_init(); curl_setopt($ctrl, CURLOPT_URL, "https://sample.com/question/add-question.php"); curl_setopt($ctrl, CURLOPT_POST, TRUE); curl_setopt($ctrl, CURLOPT_POSTFIELDS, $transfer); curl_setopt($ctrl, CURLOPT_RETURNTRANSFER, TRUE); $response = curl_exec($ctrl); curl_close($ctrl); $response = json_decode($response); echo $response; ?> If I were to echo $transfer it would read: { "prompt":"Write a function named test that takes 2 argument(s) and adds them. The type of the arguments passed into the function and the value to be returned is int. The arguments for the function should be arg1 and arg2 depending on the number of arguments the function needs.", "functionName":"test", "argumentNames":["arg1","arg2"], "testCases":{"input":["2","2"], "output":"4"} } I would like to echo the response from the url I am sending the json too but instead, I get nothing back. However the url in the curl sequence (https://sample.com/question/add-question.php) does output a json on the webpage: {"message":"An unknown internal error occured","success":false} How am I not able to grab this and echo it in my original code snippet? Is it something wrong with my curl method?
Try setting the header to say you are sending JSON... curl_setopt($ctrl, CURLOPT_HTTPHEADER, array( 'Content-Type: application/json', 'Content-Length: ' . strlen($transfer)) ); For the HTTPS, you may also need... curl_setopt($ctrl, CURLOPT_SSL_VERIFYPEER, false); You also may try... curl_setopt($ctrl, CURLOPT_FOLLOWLOCATION, 1);
Modifying php script to have POST request in cURL for a JSON upload
I have an existing PHP script, which essentially connects to 2 databases each on a different server and performs a few MySQL queries on each. The ultimate results are stored in a data array which is used to write said results into a JSON file. All of this works perfectly. The data is inserted into the mysql table correctly and the JSON file is exactly the way it should be. However, I need to add a block to the end of my script that makes a POST request to one of our affiliate's API and upload the info there. We're currently manually uploading this JSON file to the api instance but we have the configuration data for their server to use in a POST request now so that when this script is run it automatically sends the data rather than us having to manually update it. The main thing is I'm not exactly sure how to go about that. I've started with code for doing this but I'm not familiar with cURL so I don't know the best way to structure this in php. Here is an example the affiliate gave me in cURL command line syntax: curl \ -H "Authorization: Token AUTH_TOKEN" \ -H "Content-Type: CONTENT_TYPE" \ -X POST \ -d '[{"email": "jason#yourcompany.com", "date": "8/16/2016", "calls": "3"}]' \ https://endpoint/api/v1/data/DATA_TYPE/ I have my auth token, my endpoint URL and my content type is JSON, which can be seen in my code below. Also, I have an array instead of the example for the body above. and here's the affected part of my code: //new array specifically for the final JSON file $content2 = []; //creating array for new fetch since it now has the updated extension IDs while ($d2 = mysqli_fetch_array($data2, MYSQLI_ASSOC)) { // Store the current row $content2[] = $d2; } // Store it all into our final JSON file file_put_contents('ambitionLog.json', json_encode($content2, JSON_PRETTY_PRINT )); //Beginning code to upload to Ambition API via POST $url = 'endpoint here'; //Initiate CURL $ch = curl_init($url); //JSON data $jsonDataEncodeUpload = json_encode($content2, JSON_PRETTY_PRINT); //POST via CURL curl_setopt($ch, CURLOPT_POST, 1); //attach JSON to post fields curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonDataEncodeUpload); //set content type curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json')); //execuate request $postResult = curl_exec($ch); So, like I said, nothing about the file or the data needs to be changed, I just need to have this cURL section take the existing array that's being written to a JSON file and upload it to the API via post. I just need help making my php syntax for curl match the command line example. Thanks for any possible help.
Have you tried with file_get_contents ( http://en.php.net/file_get_contents ). $postdata = http_build_query( array( 'var1' => 'some content', 'var2' => 'doh' ) ); $opts = array('http' => array( 'method' => 'POST', 'header' => 'Content-type: application/x-www-form-urlencoded', 'content' => $postdata ) ); $context = stream_context_create($opts); $result = file_get_contents('http://example.com/submit.php', false, $context); I have found the answer on stackoverflow How to post data in PHP using file_get_contents?
Here is worked example of code. Check $err may be it will be helpful. $ch = curl_init($url); curl_setopt($ch, CURLOPT_TIMEOUT, 5); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $_POST('data')); curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type:application/json']); $result = curl_exec($ch); $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); $err = curl_error($ch); curl_close($ch);
API gives a JSON response, but PHP doesn't treat it as JSON on the HTTP request, only if I copy to a local file
I am using an API that gives a JSON response. If I copy that response into a 'test.txt' file and retrieve data from it - it's fine. However, if I try to #file_get_contents directly on the HTTPS url, I get a non-object. function fetchMeasurments($url, $energyCoefficient, $filePrefix) { $connectionSettings = stream_context_create(array('http'=> array( 'timeout' => 5 ) )); $jsonData = #file_get_contents($url, false, $connectionSettings); $obj = json_decode($jsonData); if( is_null($obj) ){ echo 'null'; die(); }else{ echo 'not null'; die(); } If I use test.txt - I get 'not null', but if I use the HTTPS url, I get null. Any thoughts? Here is the JSON response: {"overview":{"lastUpdateTime":"2014-10-27 11:03:15","lifeTimeData":{"energy":2.1047042E7,"revenue":2639.4795},"lastYearData":{"energy":2.105334E7},"lastMonthData":{"energy":1388652.8},"lastDayData":{"energy":749.25397},"currentPower":{"power":817.0}}}
I think you should really consider using CURL instead of file_get_contents(). Curl has support for secure connections and you will not have problems with https. Morover suppresion of errors is not a good idea. Here you have tutorial how to make CURL connections with https http://unitstep.net/blog/2009/05/05/using-curl-in-php-to-access-https-ssltls-protected-sites/ function getData($url) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); $response = curl_exec($ch); curl_close($ch); return $response; } Use this function instead of file_get_contents(). Notice this is very basic function without setting headers, error handling and certificate acceptation.