PHP Get Content of HTTP 400 Response - php

I am using PHP with the Amazon Payments web service. I'm having problems with some of my requests. Amazon is returning an error as it should, however the way it goes about it is giving me problems.
Amazon returns XML data with a message about the error, but it also throws an HTTP 400 (or even 404 sometimes). This makes file_get_contents() throw an error right away and I have no way to get the content. I've tried using cURL also, but never got it to give me back a response.
I really need a way to get the XML returned regardless of HTTP status code. It has an important "message" element that gives me clues as to why my billing requests are failing.
Does anyone have a cURL example or otherwise that will allow me to do this? All my requests currently use file_get_contents() but I am not opposed to changing them. Everyone else seems to think cURL is the "right" way.

You have to define custom stream context (3rd argument of function file_get_contents) with ignore_errors option on.

As a follow-up to DoubleThink's post, here is a working example:
$url = 'http://whatever.com';
//Set stream options
$opts = array(
'http' => array('ignore_errors' => true)
);
//Create the stream context
$context = stream_context_create($opts);
//Open the file using the defined context
$file = file_get_contents($url, false, $context);

Related

SoapClient call returns 500 Internal Server Error

I am trying to connect to an API using PHP and its built-in SoapClient. I have checked against the url I was given through the ill-formatted documents the client gave and $client->__getFunctions() returns a list of three functions. HelloWorld($name), which responds with Hello ~name~, shows me that I am communicating with the server through the SoapClient call and the URL is correct.
However, when I try to access one of the other methods that __getFunctions() gives me, even after copy/pasting the XML from the docs and putting in my own credentials, I am still being given an Internal Server Error faultstring and 500 as faultcode from the SoapFault object.
I am sure that it is my own XML string that is causing the issue but I cannot for the life of me figure out how. Reaching out to the API provider directly hasn't proven helpful. This is my first time dealing with Soap/Web Services so I am unsure of where to go from here.
I did wget http//xxx.xxx.xxx?wsdl and it returned me what looks like a valid XML response, the same one I get when I go directly to the url in the browser. What should I be looking into in order to solve this issue? All of the past API's I've dealt with have been JSON/RESTful so I feel out of my element trying to debug PHP errors.
Edit
I have slowly deleted parts of my method call and parts of my XML string, trying to trigger a different error or something in order to find what I need to fix. What I have found is that by not passing in my XML string, I get a valid response from the $client->FunctionCall(...). It's an "this isn't right" message but it's a message! In fact, passing that function ANYTHING for the xml parameter causes the 500 http faultcode/faultstring. Does this mean that my XMl is poorly formatted or does it mean that there is an issue on their end handling requests?
Second Edit
If I make my $client decleration as follows, I get the faultstring Could not connect to host
$opts = array(
'ssl' => array('ciphers'=>'RC4-SHA')
);
$client = new SoapClient($CREDS['orderingWSDL'], array (
"encoding"=>"ISO-8859-1",
'stream_context' => stream_context_create($opts),
'exceptions'=>true,
));
I am getting more confused the longer I try to fix this.
Sometimes a 500 status coming from a SOAP service could be a SoapFault exception being thrown. To help your troubleshooting, you'll want to be able to inspect both your request XML, and the response XML.
Put your code in try/catch blocks, and use $client->__getLastRequest() and $client->__getLastResponse() to inspect the actual XML.
Example:
$client = new SoapClient('http//xxx.xxx.xxx?wsdl', array('soap_version'=>SOAP_1_1,'trace' => 1,'exceptions' => true));
try {
$response = $client->someFunction();
var_dump($response);
} catch (Exception $e) {
var_dump($e->getMessage());
var_dump($client->__getLastRequest());
var_dump($client->__getLastResponse());
}

cUrl alternatives to get POST answer on a webpage

I would like to get the resulting web page of a specific form submit. This form is using POST so my current goal is to be able to send POST data to an url, and to get the HTML content of the result in a variable.
My problem is that i cannot use cUrl (not enabled), that's why i ask for your knowledge to know if an other solution is possible.
Thanks in advance
See this, using fsockopen:
http://www.jonasjohn.de/snippets/php/post-request.htm
Fsockopen is in php standard library, so all php fron version 4 has it :)
try file_get_contents() and stream
$opts = array( 'http'=>array('method'=>"POST", 'content' => http_build_query(array('status' => $message)),));
$context = stream_context_create($opts);
// Open the file using the HTTP headers set above
$file = file_get_contents('http://www.example.com/', false, $context);

How to add a parameter to the request header sent by a PHP script?

I'm trying to use a web service REST API for which I need to add a parameter for authorization (with the appropriate key, of course) to get a XML result. I'm developing in PHP. How can I add a parameter to the request header in such a situation?
Edit: The way I'm doing the request right now is $xml = simplexml_load_file($query_string);
Are you using curl? (recommended)
I assume that you are using curl to do these requests towards the REST API, if you aren't; use it.
When using curl you can add a custom header by calling curl_setopt with the appropriate parameters, such as in below.
curl_setopt (
$curl_handle, CURLOPT_HTTPHEADER,
array ('Authentication-Key: foobar')
); // make curl send a HTTP header named 'Authentication-key'
// with the value 'foobar'
Documentation:
PHP: cURL - Manual
PHP: curl_setopt - Manual
Are you using file_get_contents or similar?
This method is not recommended, though it is functional.
Note: allow_url_fopen needs to be enabled for file_get_contents to be able to access resources over HTTP.
If you'd like to add a custom header to such request you'll need to create yourself a valid stream context, as in the below snippet:
$context_options = array(
'http' =>array (
'method' => 'GET',
'header' => 'Authentication-Key'
)
);
$context = stream_context_create ($context_options);
$response = file_get_contents (
'http://www.stackoverflow.com', false, $context_options
);
Documentation:
PHP: file_get_contents - Manual
PHP: stream_context_create - Manual
PHP: Runtime Configuration, allow_url_fopen
I'm using neither of the above solutions, what should I do?
[Post OP EDIT]
My recommendation is to fetch the data using curl and then pass it off to the parser in question when all the data is received. Separate data fetching from the processing of the returned data.
[/Post OP EDIT]
When you use $xml = simplexml_load_file($query_string);, the PHP interpreter invokes it's wrapper over fopen to open the contents of a file located at $query_string. If $query_string is a remote file, the PHP interpreter opens a stream to that remote URL and retrieves the contents of the file there (if the HTTP response code 200 OK). It uses the default stream context to do that.
There is a way to alter the headers sent by altering that stream context, however, in most cases, this is a bad idea. You're relying on PHP to always open all files, local or remote, using a function that was meant to take a local file name only. Not only is it a security problem but it also could be the source of a bug that is very hard to track down.
Instead, consider splitting the loading of the remote content using cURL (checking the returned HTTP status code and other sanity checks) and then parsing that content into a SimpleXMLElement object to use. When you use cURL, you can set any headers you want to send with the request by invoking something similar to curl_setopt($ch, CURLOPT_HTTPHEADER, array('HeaderName' => 'value');
Hope this helps.

How to load a URL and only get back the last 20k of it

I have been made aware of the Accept-Range header.
I have a URL that I am calling that always returns a 2mb file. I don't need this much and only need the last section 20-50k.
I am not sure how to go about using it? Would I need to use cURL? I am currently using file_get_contents().
Would someone be able to provide me with an example / tutorial?
Thanks.
EDIT: If this isn't possible then what is post on about? Here ...
EDIT: Ulrika! I'm not insane.
This is possible using the Range header, provided the server supports it. See the HTTP 1.1 spec. You would want to send a header in the following format in your request:
Range: bytes=-50000
This would give you the last 50,000 bytes. Adjust to whatever you need.
You can specify this header in file_get_contents using a context. For example:
// Create a stream
$opts = array(
'http'=>array(
'method' => "GET",
'header' => "Range: bytes=-50000\r\n"
)
);
$context = stream_context_create($opts);
// Open the file using the HTTP headers set above
$file = file_get_contents('http://www.example.com/', false, $context);
If you were to file_get_contents() and dump that to a passthrough 'cache' file on disk, then you could use the unix/linux tail -c to only grab back the last 20kb or so. This doesn't mitigate the actual transfer, but gets that 20kb into the application.
This is indeed possible - see this question for an example of the HTTP headers sent and received
you can't do that. You're going to have to load the entire file (which is sent in its entirety, sequentially, by the source server), and just discard most of it.
What you're asking is like "I'm tuning to this radio station on my car stereo and I only want to hear the last 5 minutes of the show, without having to wait for the rest to complete or change channels".

HTTP request failed! HTTP/1.1 505 HTTP Version Not Supported error

I'm trying to use file_get_contents() to get the response from a server and this error was encountered. Could someone tell me what is the reason and how to fix it? The portion of the code is:
$api = "http://smpp5.routesms.com:8080/bulksms/sendsms?username=$username&password=$password&source=$source&destination=$destin&dlr=$dlr&type=$type&message=$message";
$resp = file_get_contents($api);
The server responded correctly while I pasted the url in the browser.
I learned that this is caused by the server rejecting the client's HTTP version, but I have no idea why that is happening in my case.
Any help is much appreciated. Thanks in advance
I found the problem, and it was a simple coding error -- missing url encoding.
The reason I didn't notice it at first was because the code was ok before I did some editing, and I'd missed out the urlencode() function before calling the server, which caused a space in the url.
This does seem to be the reason this error occurs for most people. So if you encounter this, use urlencode() on all variables which may contain white space in it's value used as URL parameters. So in the case in my question the fixed code will look like:
$api = "http://smpp5.routesms.com:8080/bulksms/sendsms?username=$username&password=$password&source=$source&destination=$destin&dlr=$dlr&type=$type&message=" . urlencode($message);
$resp = file_get_contents($api);
Also, thanks for all of your time and responses, those were informational.
You could create a stream context with the HTTP version set to 1.0 and use that context with file_get_contents:
$options = array(
'http' => array(
'protocol_version' => '1.0',
'method' => 'GET'
)
);
$context = stream_context_create($options);
$api = "http://smpp5.routesms.com:8080/bulksms/sendsms?username=$username&password=$password&source=$source&destination=$destin&dlr=$dlr&type=$type&message=$message";
$resp = file_get_contents($api, false, $context);
By the way: Don’t forget to escape your URI argument values properly with urlencode.
I ran into the same issue and in my case the culprit was an errant newline/CRLF character at the end of the request URL, which does not get caught by urlencode() (or maybe it does encode it but it still causes the server to produce the error). Once I found the problem the requests began to work again, even without the stream context options.
Hopefully this will help others.
Can you sniff what's happening on the wire? Seeing the format of the HTTP request as it goes out on the wire would help a lot.
Without seeing that, my best guess would be that the server isn't well-implemented, and is rejecting a HTTP/1.1 request. Try setting --http1.0 on Curl and seeing what happens...
Some time we still get error with
file_get_contents($api);
in that case, try this:
fopen($api,"r");
I was also facing this same issue..
later i found that while retrieving the results from mysql, Limit $count ,
$count was -ve. fixing that the url worked fine.
There is some problem in url only, and its not a file_get_contents or http version issue..

Categories