Cannot reproduce simple POSTMAN query into php curl - php

I can send a POST request successfully with POSTMAN and when I turn the request to code I get:
curl --location --request POST 'https://webservice.apiCommerce/import' \
--form 'id=1186' \
--form 'image=#/C:/collection/img/ecomm/01.jpg'
Now, I am trying the same thing with PHP curl and I don't get the expected result.
$imagePath = "./img/$fileName";
$post = [
"id" => $id,
"image" => '#'.$imagePath
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));
curl_setopt($ch, CURLOPT_URL, $url);
$response = curl_exec($ch);
$payload = json_decode($response, true);
The request gets sent, but the image doesn't get uploaded correctly. Is there a reason why there's a mismatch? I can't figure out what's wrong. I tried removing the header and so forth, but it doesn't seem to make any difference at all. I even hard-coded the img path and it doesn't seem to work.

The first request is succeeding because it is being encoded as multipart/form-data, as uploads should be. As the curl --help menu explains, the --form name=value command specifies multipart MIME data, as opposed to the --data option and its variants. In the second request, however, you are specifying the content type as application/x-www-urlencoding. This encoding is usually preferred, but will not in this case do what you want.
From the MDN web docs:
Non-alphanumeric characters in both keys and values are percent encoded: this is the reason why this type is not suitable to use with binary data (use multipart/form-data instead)

Related

Error when trying to send file in CURL POST call

I am trying to make a call from my Laravel application to the Bullhorn API to convert a document to HTML, but it looks like the file isn't being attached to the call. Below is my code:
$data = curl_file_create("full/path/to/file.docx", 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'testcv');
$ch = curl_init();
curl_setopt($ch, CURLINFO_HEADER_OUT, 1);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
$response = curl_exec($ch);
However I receive the following 500 error:
Bad File Uploaded: the request doesn't contain a multipart/form-data or multipart/mixed stream, content type header is application/x-www-form-urlencoded
When I try to set the Content-Type explicitly:
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: multipart/form-data'
));
I still receive a 500 error, just slightly different:
Bad File Uploaded: the request was rejected because no multipart boundary was found
I don't believe it's an issue with the Bullhorn API because executing the following call through the command line works fine:
curl -X POST "https://restXXX.bullhornstaffing.com/rest-services/{corptoken}/resume/convertToHtml?format=docx&BhRestToken={bhRestToken}" -F "file=#full\path\to\file.docx"
I assume that for some reason the file isn't being attached in my PHP call but I cannot figure out why.
Any help would be greatly appreciated.
The content-type: multipart/form-data uses boundary parameter for encapsulation, you can pass the boundary value as a string
'Content-Type: multipart/form-data; boundary=---------------------------7da24f2e50046'
Boundary is a string of "--" followed by a random string.
https://www.w3.org/Protocols/rfc1341/7_2_Multipart.html
If I ever have any weird problems with requests, I always put the request into postman and test it there since it compiles most of the headers and options for you, then just hit the code button on the top right to generate code in whatever language you want.
For your case you could datadump (dd) out your $data variable and copy it into one of the postman fields then set the url as well as the request type then run it and see what you get back.
Just a suggestion on how to debug a problem like this, hope it helps! good luck!

How do I make this Salesforce cURL request in PHP?

I'm using PHP to make cURL requests to Salesforce's REST API.
I've got most of the requests I need to make figured out, but I'm not sure how to convert the following curl command on the following Salesforce API page to a cURL request in PHP:
curl https://yourInstance.salesforce.com/services/data/v20.0/sobjects/Account/customExtIdField__c/11999 -H "Authorization: Bearer token" -H "Content-Type: application/json" -d #newrecord.json -X PATCH
https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_upsert.htm
I know that that -H option is for headers, which I'm handing with the following:
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
And I think that the -X PATCH part can be accomplished with the following PHP cURL option:
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PATCH');
However, how do I handle the -d #newrecord.json part in PHP cURL?
Thanks.
You should POST the json
$post = json_encode($data);
curl_setopt($ch, CURLOPT_POSTFIELDS,$post);
What you are doing with -d #newrecord.json is uploading a (JSON) file for the endpoint to use. To replicate this in PHP, you need to pass an array with a file element to CUROPT_POSTFIELDS, like this:
$file = [
"file" => "#newrecord.json";
];
curl_setopt($ch, CURLOPT_POSTFIELDS, $file);
Make sure to give the correct file path. You can use realpath() to aid with this.
Alternatively, you could just send the JSON encoded data:
$data = [
"site" => "Stack Overflow",
"help" => true,
];
$jsonData = json_encode($data);
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonData);
Don't forget to set your Content-Type: application/json header!
Lastly, your guess about the PATCH request is correct:
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PATCH');

Translating cURL request with -G to PHP

I'm trying to use the Facebook Marketing API as detailed in this tutorial.
However I'm stumped with how to translate this suggested cURL command line request into it's PHP equivalent:
curl -G \
-d 'access_token=<ACCESS_TOKEN>' \
https://graph.facebook.com/v2.5/<LEAD_ID>
I would normally do this:
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_POST,1);
curl_setopt($ch,CURLOPT_POSTFIELDS,$access_token);
$result = curl_exec($ch);
But that produces an 'Unsupported post request' error when attempting to run it. I think I am misunderstanding what the '-G' means in the command line version?
From man curl:
-G, --get
When used, this option will make all data specified with -d, --data, --data-binary or --data-urlencode to be used in an HTTP GET request instead of the POST request that otherwise would be used. The data will be appended to the URL with a '?' separator.
There's no cURL option flag in PHP that directly corresponds to this. You can use
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
or
curl_setopt($ch, CURLOPT_HTTPGET, 'GET');
but this is hardly necessary:
CURLOPT_HTTPGET
TRUE to reset the HTTP request method to GET. Since GET is the default, this is only necessary if the request method has been changed.
You will have to specify the request parameters differently: instead of setting CURLOPT_POSTFIELDS, append them as a query string to the URL (using urlencode or the equivalent curl_escape if needed):
curl_setopt( $ch, CURLOPT_URL, $url . '?accesstoken='.urlencode('<ACCESS_TOKEN>');

replicating command line cURL in PHP

I'm integrating with a 3rd party's API, I have to POST some XML and I get some XML back.
On the CLI this works, I get a positive response.
curl -X POST -d #/tmp/file http://url/to/endpoint --header "Content-Type:application/x-www-form-urlencoded"
This, however, does not work, the response contains an error telling me my that my request XML is invalid.
$ch = curl_init();
$post = array(
'file' => '#/tmp/file'
);
curl_setopt($ch, CURLOPT_URL, 'http://url/to/endpoint');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type:application/x-www-form-urlencoded'));
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
$this->responseBody = curl_exec($ch);
curl_close($ch);
It's the same file in both cases and it's on the same server. the file is just plain text XML. The only difference that I can see is that I'm specifying a fieldname in my HTTP headers on the PHP version.
How do I send that file over using PHP to exactly replicate the CLI version, e.g. without the formdata/fieldname bit?
FWIW I can't go back to the developer of the API for a few days to ask what he's defining as 'bad XML'
Try passing the file as raw data, not in an array, by for example using file_get_contents().
So instead of:
$post = array('file' => '#/tmp/file');
Like this:
$post = file_get_contents('#/tmp/file');

uploading a local document using php

I'm trying to test a rest api for upload a local file to a https url. I am currently using curl to do it. The problem is that my POST in curl is getting converted into PUT (http://curl.haxx.se/docs/manpage.html) mentions the same.
To test from command line I'm using the following:
curl -H "Content-Type: application/json" -H "Authorization:Bearer XXXXXXXXXXXXXXXYYYYYzzzzzz" -H "Accept-Version: ~1" -H "Except: 100-continue" -H "Accept-Version: ~1 " -T "somefile.pdf" "https://abc-xyz.co/docs"
Output:
{"code":"BadMethod","message":"/docs does not support PUT"}
my php code:
$url = '"https://abc-xyz.co/docs';
$filepath = '/Users/me/Documents/somefile.pdf'; //mac path
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST" );
curl_setopt($ch, CURLOPT_HTTPHEADER,
array('Authorization: Bearer XXXXXXXXXXXXXXXYYYYYzzzzzz', 'Accept-Version: ~1', 'Except: 100-continue');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
$file = "#".$filepath;
curl_setopt($ch, CURLOPT_POSTFIELDS,$file);
$response = curl_exec($ch);
if(!CURL_ERROR($ch))
{
echo"\n The output is:".$response;
}
else
{
echo "\nUpload failed ".curl_error($ch);
exit;
}
curl_close($ch);
Output: I get parse error.
Can some one educate me with 3 things:
Can I use curl to do POST for https? if yes, how? and if no what should my approach be?
How to pass the file path name in my php? I tried "#".$filepath too but it still doesn't like it.
If I want to restrict my file upload type to be only pdf should i be using mime type? (application/pdf????)
Thanks,
DR
From the commandline, see post fileupload with curl.
From PHP, see the manual
The full data to post in a HTTP "POST" operation. To post a file, prepend a filename with # and use the full path. The filetype can be explicitly specified by following the filename with the type in the format ';type=mimetype'. This parameter can either be passed as a urlencoded string like 'para1=val1&para2=val2&...' or as an array with the field name as key and field data as value. If value is an array, the Content-Type header will be set to multipart/form-data. As of PHP 5.2.0, value must be an array if files are passed to this option with the # prefix.
curl_setopt($ch, CURLOPT_POSTFIELDS,array('someuploadname'=> "#".$filepath));

Categories