I have the following class, it's using a web service to send a request and get a JSON response back.
When i try the same thing with Chrome's Postman extension, I get a nice little response back.
class RequestController {
function __construct() {
global $config;
$this->config = $config;
}
function send_request() {
$url = $this->config['GATEWAY']['url'] . 'getbyquery';
$json_data = '{"query":{"AllFields":true,"ConditionSetOperator":0,"ConditionSets":[],"Distinct":false,"Fields":["jay_alb","jay_levelms"],"Links":[],"Orders":[],"RecordType":"jay_lifeinsurance","Top":0}}';
$data = array($json_data);
$options = array(
'http' => array(
'header' => "Content-type: application/json\r\n",
'method' => 'POST',
'content' => http_build_query($data),
),
);
$context = stream_context_create($options);
print "<pre>";
print_r($options);
print "</pre>";
$result = file_get_contents($url, false, $context);
$data = json_decode($result);
var_dump($data);
}
}
However when I'm using my class I get an error.
Warning: file_get_contents(http://crm-gateway.premier.com.au/GatewayService.svc/getbyquery) [function.file-get-contents]: failed to open stream: HTTP request failed! HTTP/1.1 411 Length Required in C:\Program Files (x86)\Apache Software Foundation\Apache2.2\htdocs\crm\includes\classes\RequestController.php on line 32
Can you please point out what I'm doing wrong?
Thanks,
Related
Hi: I don't understand where I'm making errors, I'm calling fopen with an url
I have this function that should do POST requests:
function do_post(string $url, $params=""): string {
$options = array(
'http' => array(
'header' => "Length: ".strlen($params)."\r\n"." Content-Type: application/json\r\n",
'method' => 'POST',
'content' => $params
)
);
$context = stream_context_create($options);
$fp = fopen($url,'rb',false,$context);
if(!$fp) {
throw new ErrorException("post error - fopen");
}
$ret = #stream_get_contents($fp);
if(!$ret) {
throw new ErrorException("post error - get contents");
}
return $ret;
}
I call it like:
do_post('http://127.0.0.1:9191/dummyresource/DUMMYOUT.php?user=u1&status=ON');
But I got this error:
fopen(http://127.0.0.1:9191/dummyresource/DUMMYOUT.php?user=u1&status=ON):
failed to open stream: HTTP request failed! HTTP/1.1 411 Length
Required
I also added this line just before the fopen call but does nothing:
$url = str_replace('&', "&", $url);
How could I fix?
EDIT:
tested with Content-Length
I got
PHP Warning:
fopen(http://127.0.0.1:9191/dummyresource/DUMMYOUT.php?user=u1&status=ON):
failed to open stream: HTTP request failed! HTTP/1.1 400 Bad Request
The error I get:
Warning: file_get_contents(https://api.imgur.com/3/image): failed to open stream: HTTP request failed! HTTP/1.1 403 Permission Denied in
C:\xampp\htdocs\sn0\classes\Image.php on line 22
Notice: Trying to get property of non-object in
C:\xampp\htdocs\sn0\classes\Image.php on line 25
Notice: Trying to get property of non-object in
C:\xampp\htdocs\sn0\classes\Image.php on line 25
Here's my Image.php file:
<?php
class Image {
public static function uploadImage($formname, $query, $params) {
$image = base64_encode(file_get_contents($_FILES[$formname]['tmp_name']));
$options = array('http'=>array(
'method'=>"POST",
'header'=>"Authorization: Bearer ###\n".
"Content-Type: application/x-www-form-urlencoded",
'content'=>$image
));
$context = stream_context_create($options);
$imgurURL = "https://api.imgur.com/3/image";
if ($_FILES[$formname]['size'] > 10240000) {
die('Image too big, must be 10MB or less!');
}
$response = file_get_contents($imgurURL, false, $context);
$response = json_decode($response);
$preparams = array($formname=>$response->data->link);
$params = $preparams + $params;
DB::query($query, $params);
}
}
?>
You making bad request.
At the beginning you need to generate your Client ID (more info # https://api.imgur.com/#registerapp)
To do this go to https://api.imgur.com/oauth2/addclient
and
Select Anonymous usage without user authorization option as Authorization Type.
Use Authorization: Client-ID not Bearer, you can keep file_get_contents (so - then you need change only authorization header) but CURL will be better for this.
Example with CURL:
<?php
class Image
{
public static function uploadImage($formname, $query, $params)
{
$client_id = 'YOUR CLIENT ID';
$image = base64_encode(file_get_contents($_FILES[$formname]['tmp_name']));
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://api.imgur.com/3/image.json',
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => array(
'Authorization: Client-ID ' . $client_id
) ,
CURLOPT_POST => TRUE,
CURLOPT_RETURNTRANSFER => TRUE,
CURLOPT_POSTFIELDS => array(
'image' => $image
)
));
$out = curl_exec($curl);
curl_close($curl);
$response = json_decode($out);
$preparams = array(
$formname => $response->data->link
);
$params = $preparams + $params;
DB::query($query, $params);
}
}
file_get_contents() is used for GET requests. You need to use CURL in PHP in order to make a POST request from a server to another.
I need to send a POST request to another file called global.php, for this I try this code below:
$url = 'global.php';
$data = array('stack' => 'overflow');
$options = array(
'http' => array(
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'method' => 'POST',
'content' => http_build_query($data)
)
);
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
var_dump($result);
This is the global.php file that should process the request:
if(isset($_POST['stack'])){
echo 'exists';
}else{
echo 'error';
}
The problem is that instead of the command var_dump ($ result); show exists, it shows the PHP code? how can I solve this problem?
And why when I try to do the same thing using ajax it returns me the text exists and not PHP code?
You should use full url, to process php file through server.
$url = 'http://YOURURL.com/global.php';
AJAX call is made from browser, to absolute URL, thats why You are getting desired response.
I have a html page which sends a get request to php.
This is the code snippet in the php file
<?php
// Create a stream
$opts = array(
'http'=>array(
'method'=>'GET',
)
);
$context = stream_context_create($opts);
//echo("http://services.my511.org/Transit2.0/GetNextDeparturesByStopName.aspx?token={$_GET['token']}&agencyName={$_GET['agency']}&stopName={$_GET['stopname']}");
// Open the file using the HTTP headers set above
$file = file_get_contents("http://services.my511.org/Transit2.0/GetNextDeparturesByStopName.aspx?token={$_GET['token']}&agencyName={$_GET['agency']}&stopName={$_GET['stopname']}", false, $context);
//$file = file_get_contents("http://services.my511.org/Transit2.0/GetNextDeparturesByStopName.aspx?token=123-456-789&agencyName=SF-MUNI&stopName=The%20Embarcadero%20and%20Folsom%20St", false, $context);
echo(json_encode(simplexml_load_string($file)));
?>
Developer Console Output :
Warning: file_get_contents(http://services.my511.org/Transit2.0/GetNextDeparturesByStopName.aspx?token=123-456-789&agencyName=BART&stopName=Powell St. (SF)): failed to open stream: HTTP request failed! HTTP/1.1 400 BAD_REQUEST
As you can see from the developer console output, in the url request sent there are BART&stopName amp;amp; being inserted in the url which I'm not doing. The request fails due to this. Any solution around this?
Try the below code, this will make sure that you're stuff is properly URI encoded.
$params = [
'token' => $_GET['token'],
'agencyName' => $_GET['agency'],
'stopName' => $_GET['stopname']
];
$file = file_get_contents(sprintf("http://services.my511.org/Transit2.0/GetNextDeparturesByStopName.aspx?%s", http_build_query($params));
echo(json_encode(simplexml_load_string($file)));
Try this one:
$data = array('token'=>$_GET['token'],
'stopname'=>$_GET['stopname'],
'agency'=>$_GET['agency'],
);
$url = "http://services.my511.org/Transit2.0/GetNextDeparturesByStopName.aspx?".$data;
$file = file_get_contents($url, false, $context);
echo(json_encode(simplexml_load_string($file)));
Note: I have modified my answer base on your comment.
You can try this way to clean out the url:
<?php
// Create a stream
$opts = array(
'http'=>array(
'method'=>'GET',
)
);
$context = stream_context_create($opts);
$url= "http://services.my511.org/Transit2.0/GetNextDeparturesByStopName.aspx?";
$query = array(
"token" =>$_GET['token'],
"agencyName"=>$_GET['agency'],
"stopName"=>$_GET['stopname']
);
$url = $url.http_build_query($query);
$url = rawurldecode($url);
print_r($url);
$file = file_get_contents($url, false, $context);
echo(json_encode(simplexml_load_string($file)));
?>
I'm trying to use file_get_contents together with stream_context_create to make POST requests. My code so far:
$options = array('http' => array(
'method' => 'POST',
'content' => $data,
'header' =>
"Content-Type: text/plain\r\n" .
"Content-Length: " . strlen($data) . "\r\n"
));
$context = stream_context_create($options);
$response = file_get_contents($url, false, $context);
It works fine, however, when an HTTP error occurs, it spits out a warning:
file_get_contents(...): failed to open stream: HTTP request failed! HTTP/1.0 400 Bad Request
and returns false. Is there a way to:
suppress a warning (I'm planning to throw my own exception in case of failure)
obtain the error information (at least, the response code) from the stream
http://php.net/manual/en/reserved.variables.httpresponseheader.php
$context = stream_context_create(['http' => ['ignore_errors' => true]]);
$result = file_get_contents("http://example.com", false, $context);
var_dump($http_response_header);
None of the answers (including the one accepted by OP) actually satisfy the two requirements:
suppress a warning (I'm planning to throw my own exception in case of failure)
obtain the error information (at least, the response code) from the stream
Here's my take:
function fetch(string $method, string $url, string $body, array $headers = []) {
$context = stream_context_create([
"http" => [
// http://docs.php.net/manual/en/context.http.php
"method" => $method,
"header" => implode("\r\n", $headers),
"content" => $body,
"ignore_errors" => true,
],
]);
$response = file_get_contents($url, false, $context);
/**
* #var array $http_response_header materializes out of thin air
*/
$status_line = $http_response_header[0];
preg_match('{HTTP\/\S*\s(\d{3})}', $status_line, $match);
$status = $match[1];
if ($status !== "200") {
throw new RuntimeException("unexpected response status: {$status_line}\n" . $response);
}
return $response;
}
This will throw for a non-200 response, but you can easily work from there, e.g. add a simple Response class and return new Response((int) $status, $response); if that fits your use-case better.
For example, to do a JSON POST to an API endpoint:
$response = fetch(
"POST",
"http://example.com/",
json_encode([
"foo" => "bar",
]),
[
"Content-Type: application/json",
"X-API-Key: 123456789",
]
);
Note the use of "ignore_errors" => true in the http context map - this will prevent the function from throwing errors for non-2xx status codes.
This is most likely the "right" amount of error-suppression for most use-cases - I do not recommend using the # error-suppression operator, as this will also suppress errors like simply passing the wrong arguments, which could inadvertently hide a bug in calling code.
Adding few more lines to the accepted response to get the http code
function getHttpCode($http_response_header)
{
if(is_array($http_response_header))
{
$parts=explode(' ',$http_response_header[0]);
if(count($parts)>1) //HTTP/1.0 <code> <text>
return intval($parts[1]); //Get code
}
return 0;
}
#file_get_contents("http://example.com");
$code=getHttpCode($http_response_header);
to hide the error output both comments are ok, ignore_errors = true or # (I prefer #)
To capture the error message when file_get_contents returns FALSE, write a function which uses ob_start and ob_get_contents to capture the error message that file_get_contents writes to stderr.
function fileGetContents( $fileName )
{
$errmsg = '' ;
ob_start( ) ;
$contents = file_get_contents( $fileName );
if ( $contents === FALSE )
{
$errmsg = ob_get_contents( ) ;
$errmsg .= "\nfile name:$fileName";
$contents = '' ;
}
ob_end_clean( ) ;
return (object)[ 'errmsg' => $errmsg, 'contents' => $contents ];
}
I go to this page with kind of a different issue, so posting my answer. My problem was that I was just trying to suppress the warning notification and display a customized warning message for the user, so this simple and obvious fix helped me:
// Suppress the warning messages
error_reporting(0);
$contents = file_get_contents($url);
if ($contents === false) {
print 'My warning message';
}
And if needed, turn back error reporting after that:
// Enable warning messages again
error_reporting(-1);
#file_get_contents and ignore_errors = true are not the same:
the first doesn't return anything;
the second suppresses error messages, but returns server response (e.g. 400 Bad request).
I use a function like this:
$result = file_get_contents(
$url_of_API,
false,
stream_context_create([
'http' => [
'content' => json_encode(['value1' => $value1, 'value2' => $value2]),
'header' => 'Authorization: Basic XXXXXXXXXXXXXXX',
'ignore_errors' => 1,
'method' => 'POST',
'timeout' => 10
]
])
);
return json_decode($result)->status;
It returns 200 (Ok) or 400 (Bad request).
It works perfectly and it's easier than cURL.