<?php
$this->client = new \GuzzleHttp\Client;
try {
$response = $this->client->request('get', $url);
$result = json_decode($response->getBody());
Log::save($result);
} catch (RequestException $e) {
Log::save($e->getMessage());
}
If the target page has internal server error 500 situation, I will get the error message Client error: 404, actually the target page has show what the bug is if I use the browser to open it, I want to save those PHP error message to log, but I don't know how to got when using Guzzle.
There are a couple of different ways you can proceed:
If you are using Guzzle 6+ and you are using the default
HandlerStack (creating the client with no handler new \GuzzleHttp\Client(); the default behaviour will be for the request
to throw a GuzzleHttp\Exception\ServerException exception. In this case, all you have to do is wrap your request in a try / catch block (as shown above).
If you are manually creating your
HandlerStack $stack = new \GuzzleHttp\HandlerStack(); $client = new \GuzzleHttp\Client(['handler' => > $stack,]); then the \GuzzleHttp\Middleware::httpErrors middleware has not been loaded onto the stack, and you will have to trap it within your own middleware or by passing a callable to the 'on_headers' request option.
References:
Guzzle Request Options - http_errors
Guzzle Handlers and Middleware
Guzzle Request Options - on_headers
Related
Using php and the Slim Framework, is there a way I can set up the error-handler so my custom Exceptions that can automatically trigger the desired HTTP response, without forcing me to catch all the different exception types?
I know such examples from my projects with python Flask, but not the php equivalent.
For example, regardless where the exception is thrown in the code, I want my custom BadCustomerDataException() to trigger a HTTP 400 response, and the WaitingForResourceException() to trigger a 423 response, and the FaultyServerIsDeadAgainException() to trigger a 500 response.
Currently I'm using Slim version 3, with a planned update to version 4.
In Slim 4 you can add a custom error handler to the ErrorMiddleware. You can also add your own Middleware before the ErrorMiddleware to catch and map your own exceptions:
Example
<?php
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Slim\Exception\HttpNotFoundException;
use Slim\Middleware\ErrorMiddleware;
use Slim\Psr7\Response;
// ...
// HttpNotFound Middleware
$app->add(function (
ServerRequestInterface $request,
RequestHandlerInterface $handler
) {
try {
return $handler->handle($request);
} catch (HttpNotFoundException $httpException) {
$response = (new Response())->withStatus(404);
$response->getBody()->write('404 Not found');
return $response;
}
});
$app->add(ErrorMiddleware::class);
Source
So I have installed the Guzzle library version 6 according to TeamUp calendar documentation. However, when I try to run the code below I get
Fatal error: Call to undefined method GuzzleHttp\Psr7\Response::isSuccessful()
code:
<?php
include 'vendor/autoload.php';
define('API_KEY','****ww9d5ea2b0540ba1e02c08100b0e5**');
$client = new GuzzleHttp\Client(['headers' => ['Teamup-Token' => API_KEY]]);
$res = $client->get('https://api.teamup.com/ks************/events?startDate=2016-08-21&endDate=2016-08-25');
if ($res->isSuccessful()) {
echo $res->getBody();
// {"event":{ ... }}
}
Shouldn't be contained in Library?
Anyone?
Yes, there is no method isSuccessful.
By default Guzzle will throw exception if server return error
http://docs.guzzlephp.org/en/latest/quickstart.html
A GuzzleHttp\Exception\ServerException is thrown for 500 level errors
if the http_errors request option is set to true.
A GuzzleHttp\Exception\ClientException is thrown for 400 level errors
if the http_errors request option is set to true.
In the event of a networking error (connection timeout, DNS errors,
etc.), a GuzzleHttp\Exception\RequestException is thrown.
Anyway, you can check the status code of the response using
$res->getStatusCode();
The upgrade notes from Guzzle 5.0 to Guzzle 6.0 say:
GuzzleHttp\Message\Response::isSuccessful() and other related methods have been removed. Use getStatusCode() instead.
I can't figure out how I can throw an exception from Guzzle future response handler.
Here's my code:
<?php
require 'vendor/autoload.php';
$client = new \GuzzleHttp\Client();
$req = $client->createRequest('GET', 'http://www.google.com', array(
'future' => true,
));
echo "Sending request\n";
$response = $client->send($req);
try {
$response->then(function ($data) {
echo "Response is received\n";
throw new Exception('Test');
})->then(function () {
// success handler
}, function (Exception $exception) {
echo "Error handler invoked\n";
throw $exception;
});
} catch (Exception $e) {
echo "Exception catched\n";
}
echo "Finish\n";
The catch block is never reached in this case.
You are working with promises when using asynchronous Guzzle requests. Using the then() function off of a FutureResponse will create a promise that is fulfilled or rejected when the request completes. If an error occurs while sending, the promise is rejected, which means the second callback provided to the then function is invoked. When a request completes successfully, it is resolved, and the first callback provided to the then function is invoked. When an exception is thrown in any of the promise functions, the exception is caught inside of the promise and forwarded to the next error handler in the chain. In your example, if the request succeeds, then you throw an exception which will trigger the error callback. Throwing an exception in the error callback will either forward the exception to the next error callback in the promise chain, or silently eat the error (in your case, there are no further error callbacks to trigger).
The React Promises library that is used by Guzzle has more documentation on resolution and rejection forwarding of promises: https://github.com/reactphp/promise#how-promise-forwarding-works. The author of this library is looking into adding a done() function that can be used as a terminal promise handler that actually throws unhandled exceptions.
Asynchronous means that your script will not wait for the response to come back from the server, rather will just send the request and continue executing. In this case, the script reaches its end of life before the response returns, so none of the callbacks are ever executed.
Add this line after the catch to block the script's execution until the response comes back.
$response->getStatusCode();
If you provide more info on what you want to achieve, we might be able to help you further.
Using https://github.com/abraham/twitteroauth:
function getTwitterFeed($token_array){
require_once('twitteroauth/twitteroauth.php');
$oauth_token = $token_array['access_token'];
$oauth_token_secret = $token_array['access_token_secret'];
$connection = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET, $oauth_token, $oauth_token_secret);
$response = $connection->get("statuses/user_timeline");
//...do stuff with the response
}
I want to catch errors or exceptions for authentication problems (invalid token or token secret) and/or "rate limit exceeded."
I can't find anything on error handling for this library anywhere. How can I accomplish this?
Look into the Exceptions part of the PHP manual, the library uses them extensively.
Basically they will look like this:
try {
// your code here
} catch (OAuthException $e) {
// your error handling here
}
the OauthException class is the what the library uses for every throw.
Edit0:
Unfortunately the errors returned from the actual twitter API not converted into exceptions by the library so you will have to check the return values from get() and other calls, and look for the "error" key, errors will look something like this:
object(stdClass)[5]
public 'error' => string 'Could not authenticate you.' (length=27)
public 'request' => string '/1/account/verify_credentials.json?aauth_consumer_key=CONSUMER_KEY_HERE&oauth_nonce=cfbf6a55b26683750a166f14aeb5ed84&oauth_signature=c96MciQcODQD5jUAkyrAmSxXa0g%3D&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1342379970&oauth_token=alma&oauth_version=1.0' (length=258)
also it will set the API instance's http_code code property to the response's http status, if that's not 200 it will indicate error.
Edit1:
I've created a fork of the library that will generate exceptions for every request that returns non 200 HTTP status, the exception's code will be the http status that twitter returns and message is the message (if exists), twitter's http error code listing will help decode the errors.
Also introduced a new Exception subclass for convenience named TwitterOauthException, every exception that thrown by the library subclasses this one.
As detailed here: Need assistance with Kohana 3 and catch all route turning into a 404 error as the accepted answer to the question, I'm attempting to catch errors thrown by Kohana to display pretty error pages and send correct HTTP codes.
Here's a simplified version to demonstrate the problem:
try {
// Instantiate your Request object
$request = Request::instance();
// The give it a try, to see if its a valid request
$request->execute();
}
catch (Kohana_Request_Exception $e) {
header('Content-Type: text/html; charset='.Kohana::$charset, TRUE, 404);
echo Request::factory('err/404')->send_headers()->execute()->response;
exit;
}
echo $request->send_headers()->response;
So I navigate to a non-existent URL such as http://example.local/moo/ and I get the following response
Kohana_Request_Exception [ 0 ]: Unable to find a route to match the URI: moo
Here is what's happening-- The request is being tried, failing with a Kohana_Request_Exception, it's being caught BUT when I try to build a new request object, Request::factory('err/404') THAT request throws the error from my first request....!? wtf??
I've fiddled with it for a good hour and am as puzzled as when I started. Shouldn't the new request from the factory have no knowledge of the old request?? Why is this code malfunctioning when I essentially copied it from the d00d's answer?
// Release version and codename
const VERSION = '3.0.7';
const CODENAME = 'hattrick';
Someone point me in the right direction.. thx guys.
It's because within Request::factory('err/404'), the err/404 part is a URL that is trying to be matched by your routes as well. Will it ever match, i.e. do you have a route with something like this...
Route::set('errors', 'err/<action>', array('action' => '404|500')) {}
You should also be sending a 404 via...
$request->status = 404;
Aha! Thanks guys but I got it figured.. I shoulda looked at the stack trace a little closer, the error page's template controller's before() method was throwing a new error as it was attempting to check authentication using Request::instance()I changed it to Request::current() and it's all shiny.
Thanks for the help!