How to reset CURLOPT_CUSTOMREQUEST - php

I’m using a REST API which, among other things, uses the DELETE method like this:
DELETE /resources/whatever/items/123
To access this using PHP I’m using cURL like this:
self::$curl = curl_init();
curl_setopt_array(self::$curl, array(
CURLOPT_AUTOREFERER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_RETURNTRANSFER => true,
));
As you can see, my cURL instance is static and will be reused for subsequent calls. This works fine when switching between “builtin” request methods. For example, in my get() method, I do something like this:
curl_setopt_array(self::$curl, array(
CURLOPT_HTTPGET => true,
CURLOPT_URL => self::BASE . 'whatever',
));
and then run curl_exec(). By explicitly setting the request method via CURLOPT_HTTPGET, a possible previous CURLOPT_POST will be cleared.
However, setting CURLOPT_CUSTOMREQUEST (for example to DELETE) will override any other builtin request method. That’s fine as long as I want to DELETE things, but calling for example curl_setopt(self::$curl, CURLOPT_HTTPGET, true) will not reset the custom method; DELETE will still be used.
I have tried setting CURLOPT_CUSTOMREQUEST to null, false or the empty string, but this will only result in a HTTP request like
/resources/whatever/items/123
i.e. with the empty string as method, followed by a space, followed by the path.
I know that I could set CURLOPT_CUSTOMREQUEST to GET instead and do GET requests without any problems, but I wonder whether there is a possiblity to reset CURLOPT_CUSTOMREQUEST.

This is actually a bug in PHP, since the original documentation states the following:
Restore to the internal default by setting this to NULL.
Unfortunately, as you can see from the source code, the option value gets cast to a string before it's passed to the underlying library.
Solution
I've written a pull request that addresses the issue and allows for NULL to be passed for the CURLOPT_CUSTOMREQUEST option value.
The above patch will take some time to get merged into the project, so until then you would have to explicitly set the method yourself once you start using this option.
Update
The fix has been applied to 5.5.11 and 5.6.0 (beta1).

Set CURLOPT_CUSTOMREQUEST to NULL and CURLOPT_HTTPGET to TRUE to reset back to an ordinary GET.

(Shrug ...) And what I wound up doing in my API is to simply, "set it every time." My POST routine simply sets a custom-header of "POST", and so on. Works great.
I found that, once you do set a custom-header, it "sticks." Future calls which then attempt to do ordinary GET, POST, PUT start to fail. I experimented with the suggestions listed earlier in this post (with PHP-7), and didn't very-quickly meet with success ... so: "to heck with it, this isn't elegant, but it works."

Related

Send a complex data using curl in PHP

I have searched a lot, and found many related questions and forums related to this, but this one is a challenging one.
I'm trying to POST a complex array via curl. It has to be form-data while the first value in the array is of type JSON.
The two other values of array are two images which are uploaded and ready to send.
I tried to run it in Postman, and works perfectly fine. I used the generated PHP code from Postman, but it is not working. Seems like postman is handling some of its tricks without revealing them to us.
Any way, I'm posting a Postman image to illustrate what I mean:
As you can see, I'm sending the data in form-data tab, my first value (param1) is a JSON with content-type application/json, the second and third values are images uploaded in Postman.
This works just fine in Postman.
The problem is, if I set Content-Type:multipart/form-data in header, the destination server throws an error saying the content-type must be JSON.
If I set the Content-Type:application/json in header, the destination server says content must be of type Multipart.
Somehow, I need to set both content-types. The main one as form-data and the one for param1 as JSON.
I paste the Postman code as well, may that be a good start for you fellas to help out with the code.
Postman Code:
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'http://xxxxx.com/xxxx/xxx/xxxx',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => array('param1' => '{
"AgentId":"1414",
"ContractId":36529,
"Files":[
{
"FileName":"car_card_front_image.png",
"FileTypeId":2
},
{
"FileName":"car_card_back_image.png",
"FileTypeId":2
}
]
}','param2'=> new CURLFILE('/C:/images/icons/car_card_back_image.png'),'param3'=> new CURLFILE('/C:/images/icons/car_card_front_image.png')),
CURLOPT_HTTPHEADER => array(
'authenticationToken: xxxx-xxx-xx-xxxxxxxx'
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
The PHP generated code by postman, is not working. One of the reasons can be that there's no content-type mentioned in it.
I tried modifying the code, adding content-types in header and in parameter, nothing seems to work.
If Postman can do it, we should be able it too, right?
Go ahead, make as much changes as you would or suggest anything that comes to your mind, I will test them all.
Cheeeeers...
May i suggest the ixudrra/curl library ?
It would make your life easier ....
$response = Curl::to('http://example.org')
->withData( array( 'Foo' => 'Bar' ) )
->withFile( 'image_1', '/path/to/dir/image1.png', 'image/png', 'imageName1.png' )
->withFile( 'image_2', '/path/to/dir/image2.png', 'image/png', 'imageName2.png' )
->post();

Calling custom PHP in functions

TLDR: I want to use get_theme_mod() inside a PHP file other than functions.php in WordPress to use a value added through customizer.
Long version:
I am making an API call using cURL in a separate PHP file. I want to create a new panel in customizer with an inputfield that accepts the API-key for my custom PHP API call. Basically I need to know if I can use the get_theme_mod() method to call the value into my custom PHP file, store it in a variable and use it to append it to my API call.
This is my API call code
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => "https://maps.googleapis.com/maps/api/place/details/json?placeid=< GOOGLE PLACE ID >&key=< MY API KEY>",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => array(
"Cache-Control: no-cache",
"Content-Type: application/json"
),
));
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
Once the call is made, I AJAX this file into a JavaScript file where I work with the data. Which is initially why I put the API call into a separate file. My goal is for the person working on the site to simply paste an API key, or the place id for Google and have the entire process execute without having to monkey around in the source code. I have all the infrastructure in place and the call works I just wanted to eliminate the need for us to touch the source code and simply drop an API key value in the customizer and let the code do the rest.
I'm assuming you mean the theme customizer? Maybe instead save settings using the Settings API. But you should also do AJAX the "wordpress way" or use the newer REST stuff.
Directly answering your question of "how to use Wordpress functions in external PHP" see https://wordpress.stackexchange.com/questions/47049/what-is-the-correct-way-to-use-wordpress-functions-outside-wordpress-files
<?php
define('WP_USE_THEMES', false); // although you might want that to be true if you're using theme data?
require('./wp-load.php');
?>
Or maybe consider doing all that stuff in a shortcode that takes the place key and/or api key, e.g. [get-place-info placekey="xxxxx" apiKey="xxxx"] so your user can dump it anywhere, unless you specifically need it available to javascript (heck, you could have the shortcode dump JSON into the page).

PHP - cURL should I set 'AUTOREFERER' when following redirects?

TL;DR
Why should or shouldn't I set CURLOPT_AUTOREFERER => true in my cURL function (that follows a limited number of redirects)?
Long(er) Version
I have a pretty standard cURL function that return the headers for a given URL, following up-to 10 redirects...
const SINGLETIMEOUT = 8; // Seconds (is this too long?)
public static function getHeaders($url, $userAgent) {
// Initialize cURL object
$curl = curl_init($url);
// Set options
curl_setopt_array($curl, array(
CURLOPT_USERAGENT => $userAgent,
CURLOPT_HEADER => true,
CURLOPT_NOBODY => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_MAXREDIRS => 10,
CURLOPT_AUTOREFERER => true,
CURLOPT_TIMEOUT => SINGLETIMEOUT, // 5 seconds (safety!)
CURLOPT_CONNECTTIMEOUT => SINGLETIMEOUT
));
// Run it
curl_exec($curl);
// Get headers
$headers = curl_getinfo($curl);
// Close it
curl_close($curl);
return $headers;
}
The function getHeaders works great, exactly as expected. But so far in my testing, there is no difference in performance or results, whether I include CURLOPT_AUTOREFERER => true or not. There are plenty of references saying what CURLOPT_AUTOREFERER does, but beyond that I can't find anything going into more depth on that particular option.
Ok, so setting `` will
... automatically set the Referer: header field in HTTP requests where it follows a Location: redirect
So what? Why does this matter? Should I keep it in or toss it? Will it cause the results to be different for some URLs? Will some domains return erroneous headers, the same as when I send an empty user agent?
And on, and on...
Most of the examples I found to make this function did not include it - but they also didn't include many of the other options that I'm including.
Ok some basic information first: According to wikipedia:
The HTTP referer (originally a misspelling of referrer) is an HTTP header field that identifies the address of the webpage (i.e. the URI or IRI) that linked to the resource being requested. By checking the referrer, the new webpage can see where the request originated.
In the most common situation this means that when a user clicks a hyperlink in a web browser, the browser sends a request to the server holding the destination webpage. The request includes the referer field, which indicates the last page the user was on (the one where they clicked the link).
Referer logging is used to allow websites and web servers to identify where people are visiting them from, for promotional or statistical purposes.
However here's an important detail. This header is supplied by the client and the client can choose to supply it or can choose to not supply it. In addition if the client chooses to supply it then the client can supply any value it wants.
Because of this developers have learned to not really rely on the referrer value they get for anything other than statistics because of how easily it can be spoofed (you can actually set the referrer header yourself in the cURL call if you want instead of using CURLOPT_AUTOREFERER).
Therefore it's generally inconsequential to supply it when using crawlers or cURL. It's up to you if you want to let the remote site know where you came from. It should still work either way.
That being said it's not impossible for a site to present different results based on the referrer, for example I had seen a site that was checking on whether the referrer was Google in order to supply additional in-site search results, but this is the exception and not the rule and other than that the sites should always be usable anyway.

Get size of queue in twilio from rest call in php without using library

My php/Yii application interacts with twilio. I know the sid of a queue. I want to get the current size of that queue. The thing is that I can't use the twilio php library (I don't want to get into the details). I'm using curl, but I keep getting 401 errors.
This is my code:
$curl = curl_init();
curl_setopt_array($curl,array(
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_URL => 'https://api.twilio.com/2010-04-01/Accounts/AccountId/Queues/QUeueID.json',
CURLOPT_USERPWD => 'token:{AuthToken}'));
curl_exec($curl);
I don't what I'm doing wrong. I'm trying to follow the documentation:
http://www.twilio.com/docs/api/rest/queue
EDIT: I turned it into a get request, from a post request.
Also, I got a 401 unauthorized error, not a 411. Sorry about that. Typo.
SECOND EDIT:
So, I figured it out in a conversation with Kevin. Turns out that I needed:
CURLOPT_USERPWD => 'AccountID:Token'
If you are just trying to retrieve the size of a queue, you want to make a GET request, not a POST. It looks like you are setting CURLOPT_POST in your curl request.

CURLOPT_RETURNTRANSFER with curl_multi

I'm using the curl_multi functions with PHP. I already know that you can return the request contents from curl_exec when the CURLOPT_RETURNTRANSFER flag is on. However, how can we grab the request contents of multiple requests as strings when using curl_multi_exec?
Does it return an array when this flag is set? Nope, curl_multi_exec can only return true or false, without the option to return the contents like the normal one.
Turns out, the curl_multi_getcontent function, while somewhat inelegant, works for getting the contents as strings from each individual curl handle.

Categories