I need to interface with a REST webserver. When I issue a request, it responds (correctly) with HTTP response code 201 (Created), and the relevant information (JSON object) in the body.
I can verify it using cURL.
I'm trying to get the body it via PHP's file_get_contents function, specifying a correct context object, with the following code:
$context = stream_context_create(array(
'http' => array(
'method' => 'POST',
'header' => $header,
'timeout' => 10.0,
'content' => $body,
'ignore_errors' => true
)
)
);
$answer = file_get_contents($url, false, $context);
However the function always returns a false value and I cannot get the returned body.
What can I do? (I'd rather not call cURL from PHP)
OK, I've found it.
The cause was an old php version,
that did'nt handle the 'ignore_errors' parameter.
Switching to a more recent version of php, now it works.
Related
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();
We have a "legacy" script that stopped working a little while back. Pretty sure it's because the endpoint it's connecting to changed from http to https, and the old http address now returns a 301.
I've never done anything other than tiny changes to PHP scripts, so am a little out of my depth here.
Note that our PHP version is old - 5.3.0. This may well be part of the problem.
The script as-is (relevant bit anyway):
$uri = "http://www.imf.org/external/np/fin/data/rms_mth.aspx"
."?SelectDate=$date&reportType=CVSDR&tsvflag=Y";
$opts = array('http' => array(
'proxy' => 'tcp://internal.proxy.address:port',
'method' => 'GET',
'request_fulluri' => true)
);
$ctx = stream_context_create($opts);
$lines = file($uri, false, $ctx);
foreach ($lines as $line)
...
This returns nothing any more. The link btw is the IMF link for exchange rates, so that is open to all - if you open it you'll get a download with a rate table in it. The rest of the script basically parses this for the data we want.
Now, pretty sure our proxy is OK. Running some tests with curl gives the following results:
curl --proxy tcp://internal.proxy.address:port -v https://www.imf.org/external/np/fin/data/rms_mth.aspx?SelectDate=05/28/2020&reportType=CVSDR&tsvflag=Y
(specify https) works just fine.
curl --proxy tcp://internal.proxy.address:port -v http://www.imf.org/external/np/fin/data/rms_mth.aspx?SelectDate=05/28/2020&reportType=CVSDR&tsvflag=Y
(specify http) does not work, and shows a 301 error
curl --proxy tcp://internal.proxy.address:port -v -L http://www.imf.org/external/np/fin/data/rms_mth.aspx?SelectDate=05/28/2020&reportType=CVSDR&tsvflag=Y
(specify http with follow redirects) then works OK.
I've tried a few things after some googling. It seems I need opts for 'ssl' as well when using https. So I've made the following changes
$uri = "https://www.imf.org/external/np/fin/data/rms_mth.aspx"
."?SelectDate=$date&reportType=CVSDR&tsvflag=Y";
$opts = array('http' => array(
'proxy' => 'tcp://internal.proxy.address:port',
'method' => 'GET',
'request_fulluri' => true),
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false,
'SNI_enabled' => false)
);
Sadly, the SNI_enabled flag was introduced after 5.3.0, so I don't think this helps. There's also a follow_location context option for http, but that was introduced in 5.3.4, so also no use.
(BTW, I have little to no control over the version of PHP we have, so while I appreciate higher versions may offer better solutions, that's not a lot of use to me I'm afraid).
Basically, I am now stuck. No combination of these parameters or settings returns any data at all. I can see it works via curl and the proxy, so it's not a general connectivity issue.
Any and all suggestions gratefully received!
Update: After adding the lines to enable error reporting, the error code is for the stream connecting:
Warning: file(https://www.imf.org/external/np/fin/data/rms_mth.aspx?SelectDate=05/28/2020&reportType=CVSDR&tsvflag=Y): failed to open stream: Cannot connect to HTTPS server through proxy in /usr/bass/apps/htdocs/BASS/mods/module.XSM.php on line 79
(line 79 is the $lines = ... line)
So it doesn't connect in the php script, but running the same connection via the proxy in curl works fine. What's the difference in php that causes this?
You can use php curl functions to get the response from your given url. And then you can use explode() function to break the response line by line.
$uri = "https://www.imf.org/external/np/fin/data/rms_mth.aspx"
."?SelectDate=$date&reportType=CVSDR&tsvflag=Y";
$opts = array(
CURLOPT_URL => $uri,
CURLOPT_PROXY => 'tcp://internal.proxy.address:port',
CURLOPT_HEADER => false,
CURLOPT_RETURNTRANSFER => true
);
$ch = curl_init();
curl_setopt_array($ch, $opts);
$lines = curl_exec($ch);
curl_close($ch);
$lines = explode("\n", $lines); // breaking the whole response string line by line
foreach ($lines as $line)
...
Suppose I have an api: api.example.com, this code actually gets the contents of api.example.com/Browser/API/ping.php (this is a simple ping script). Now I want to be able to do something like api.example.com/ping/site_to_ping (keep in mind, the folder "ping" doesn't exist, neither do I have a folder for every existing site). This would then execute the following: file_get_contents("api.example.com/Browser/ping?*site_to_ping*");
Is this possible?
Sending an HTTP POST request using file_get_contents is not that hard, actually : as you guessed, you have to use the $site_to_ping parameter.
There's an example given in the PHP manual, at this page : HTTP context options (quoting) :
$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' => $site_to_ping_name
)
);
$site_to_ping = stream_context_create($opts);
$result = file_get_contents('api.example.com/Browser/ping', false, $site_to_ping);
Basically, you have to create a stream, with the right options (there is a full list on that page), and use it as the third parameter to file_get_contents -- nothing more ;-)
As a sidenote : generally speaking, to send HTTP POST requests, we tend to use curl, which provides a lot of options an all -- but streams are one of the nice things of PHP that nobody knows about... too bad...
I am going to send a Log in request to the server by using CURL in my PHP code. This request is POST and I wrote following code,
if (strpos($header, 'POST') !== false){
curl_setopt_array($curl, array(
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_HEADER => 1,
CURLOPT_URL => $url,
CURLOPT_USERAGENT => 'proxy',
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => $postParameters,
CURLOPT_COOKIE => $postCoockies
));
$respond = curl_exec($curl);
curl_close($curl); }
and if I want to say what my variables are here:
$url is the exact String after POST and before HTTP/1.1.
when I want to send the GET request also, I am using this part as my urs which would be contained all parameters in my query String.
$postParameters is the exact String that exist in POST body.
(That's a String, not an associative array)
$postCoockies in the exact String after Cookie: in my request header.
(again, that's not an associative array)
My problem is:
When I send this request, server sends me back a response to only the URL I am passing. Which is to load the login page again! it seems that the server is not receiving my parameters!
Also, when I used GET request for login (I have access to the source code of website), and sent the whole URL and parameters inside the $url, the same thing happened.
Am I wrong somewhere in sending my request?
Should I consider something else here?
I am trying to load data from a site that returns XML, but it only returns the XML once it does a redirect for security purposes. How do I configure a PHP request that will follow this redirect and receive the output?
file_get_contents should follow HTTP redirects. According to the default HTTP context options follow_location is enabled and max_redirects is 20.
In this example $xml should contain the XML of wherever the original page redirects to:
$xml = file_get_contents('http://www.example.com/');
If that doesn't work you can verify that the default context options aren't being overridden by specifying a custom context:
$context = stream_context_create(
array (
'http' => array (
'follow_location' => true,
'max_redirects' => 20
)
)
);
$xml = file_get_contents('http://www.example.com/', false, $context);