Wrap non-RequestExceptions with a RequestException
public static wrapException ( Psr\Http\Message\RequestInterface $request, Exception $e ) : |
||
$request | Psr\Http\Message\RequestInterface | |
$e | Exception | |
Результат |
public function testWrapsConnectExceptions() { $e = new ConnectException('foo'); $r = new Request('GET', 'http://www.oo.com'); $ex = RequestException::wrapException($r, $e); $this->assertInstanceOf('GuzzleHttp\\Exception\\ConnectException', $ex); }
/** * Sends an HTTP request. * * @param RequestInterface $request Request to send. * @param array $options Request transfer options. * * @return PromiseInterface */ public function __invoke(RequestInterface $request, array $options) { // Sleep if there is a delay specified. if (isset($options['delay'])) { usleep($options['delay'] * 1000); } $startTime = isset($options['on_stats']) ? microtime(true) : null; try { // Does not support the expect header. $request = $request->withoutHeader('Expect'); // Append a content-length header if body size is zero to match // cURL's behavior. if (0 === $request->getBody()->getSize()) { $request = $request->withHeader('Content-Length', 0); } return $this->createResponse($request, $options, $this->createStream($request, $options), $startTime); } catch (\InvalidArgumentException $e) { throw $e; } catch (\Exception $e) { // Determine if the error was a networking error. $message = $e->getMessage(); // This list can probably get more comprehensive. if (strpos($message, 'getaddrinfo') || strpos($message, 'Connection refused') || strpos($message, "couldn't connect to host")) { $e = new ConnectException($e->getMessage(), $request, $e); } $e = RequestException::wrapException($request, $e); $this->invokeStats($options, $request, $startTime, null, $e); return new RejectedPromise($e); } }
/** * Sends an HTTP request. * * @param RequestInterface $request Request to send. * @param array $options Request transfer options. * * @return PromiseInterface */ public function __invoke(RequestInterface $request, array $options) { // Sleep if there is a delay specified. if (isset($options['delay'])) { usleep($options['delay'] * 1000); } try { // Does not support the expect header. $request = $request->withoutHeader('Expect'); $stream = $this->createStream($request, $options); return $this->createResponse($request, $options, $stream); } catch (\InvalidArgumentException $e) { throw $e; } catch (\Exception $e) { // Determine if the error was a networking error. $message = $e->getMessage(); // This list can probably get more comprehensive. if (strpos($message, 'getaddrinfo') || strpos($message, 'Connection refused') || strpos($message, "couldn't connect to host")) { $e = new ConnectException($e->getMessage(), $request, $e); } return new RejectedPromise(RequestException::wrapException($request, $e)); } }
/** * Emits the "end" event and throws an exception if one is present. */ private function end(Transaction $trans) { // Futures will have their own end events emitted when dereferenced, // but still emit, even for futures, when an exception is present. if (!$trans->exception && $trans->response instanceof FutureInterface) { return; } $trans->request->getEmitter()->emit('end', new EndEvent($trans)); // Throw exceptions in the terminal event if the exception was not // handled by an "end" event listener. if ($trans->exception) { if (!$trans->exception instanceof RequestException) { $trans->exception = RequestException::wrapException($trans->request, $trans->exception); } throw $trans->exception; } }
public function send(RequestInterface $request) { $isFuture = $request->getConfig()->get('future'); $trans = new Transaction($this, $request, $isFuture); $fn = $this->fsm; try { $fn($trans); if ($isFuture) { // Turn the normal response into a future if needed. return $trans->response instanceof FutureInterface ? $trans->response : new FutureResponse(new FulfilledPromise($trans->response)); } // Resolve deep futures if this is not a future // transaction. This accounts for things like retries // that do not have an immediate side-effect. while ($trans->response instanceof FutureInterface) { $trans->response = $trans->response->wait(); } return $trans->response; } catch (\Exception $e) { if ($isFuture) { // Wrap the exception in a promise return new FutureResponse(new RejectedPromise($e)); } throw RequestException::wrapException($trans->request, $e); } }
/** * Emits the error event and ensures that the exception is set and is an * instance of RequestException. If the error event is not intercepted, * then the exception is thrown and we transition to the "end" event. This * event also allows requests to be retried, and when retried, transitions * to the "before" event. Otherwise, when no retries, and the exception is * intercepted, transition to the "complete" event. */ private function error(Transaction $trans) { // Convert non-request exception to a wrapped exception if (!$trans->exception instanceof RequestException) { $trans->exception = RequestException::wrapException($trans->request, $trans->exception); } // Dispatch an event and allow interception $event = new ErrorEvent($trans); $trans->request->getEmitter()->emit('error', $event); if ($trans->exception) { throw $trans->exception; } $trans->exception = null; // Return true to transition to the 'before' state. False otherwise. return $trans->state === 'before'; }
/** * Runs the state machine until a terminal state is entered or the * optionally supplied $finalState is entered. * * @param Transaction $trans Transaction being transitioned. * * @throws \Exception if a terminal state throws an exception. */ public function __invoke(Transaction $trans) { $trans->_transitionCount = 0; if (!$trans->state) { $trans->state = 'before'; } transition: if (++$trans->_transitionCount > $this->maxTransitions) { throw new StateException("Too many state transitions were " . "encountered ({$trans->_transitionCount}). This likely " . "means that a combination of event listeners are in an " . "infinite loop."); } switch ($trans->state) { case 'before': goto before; case 'complete': goto complete; case 'error': goto error; case 'retry': goto retry; case 'send': goto send; case 'end': goto end; default: throw new StateException("Invalid state: {$trans->state}"); } before: try { $trans->request->getEmitter()->emit('before', new BeforeEvent($trans)); $trans->state = 'send'; if ((bool) $trans->response) { $trans->state = 'complete'; } } catch (\Exception $e) { $trans->state = 'error'; $trans->exception = $e; } goto transition; complete: try { if ($trans->response instanceof FutureInterface) { // Futures will have their own end events emitted when // dereferenced. return; } $trans->state = 'end'; $trans->response->setEffectiveUrl($trans->request->getUrl()); $trans->request->getEmitter()->emit('complete', new CompleteEvent($trans)); } catch (\Exception $e) { $trans->state = 'error'; $trans->exception = $e; } goto transition; error: try { // Convert non-request exception to a wrapped exception $trans->exception = RequestException::wrapException($trans->request, $trans->exception); $trans->state = 'end'; $trans->request->getEmitter()->emit('error', new ErrorEvent($trans)); // An intercepted request (not retried) transitions to complete if (!$trans->exception && $trans->state !== 'retry') { $trans->state = 'complete'; } } catch (\Exception $e) { $trans->state = 'end'; $trans->exception = $e; } goto transition; retry: $trans->retries++; $trans->response = null; $trans->exception = null; $trans->state = 'before'; goto transition; send: $fn = $this->handler; $trans->response = FutureResponse::proxy($fn(RingBridge::prepareRingRequest($trans)), function ($value) use($trans) { RingBridge::completeRingResponse($trans, $value, $this->mf, $this); $this($trans); return $trans->response; }); return; end: $trans->request->getEmitter()->emit('end', new EndEvent($trans)); // Throw exceptions in the terminal event if the exception // was not handled by an "end" event listener. if ($trans->exception) { if (!$trans->exception instanceof RequestException) { $trans->exception = RequestException::wrapException($trans->request, $trans->exception); } throw $trans->exception; } }
public function send(RequestInterface $request) { $trans = new Transaction($this, $request); $fn = $this->fsm; // Ensure a future response is returned if one was requested. if ($request->getConfig()->get('future')) { try { $fn($trans); // Turn the normal response into a future if needed. return $trans->response instanceof FutureInterface ? $trans->response : new FutureResponse(new FulfilledPromise($trans->response)); } catch (RequestException $e) { // Wrap the exception in a promise if the user asked for a future. return new FutureResponse(new RejectedPromise($e)); } } else { try { $fn($trans); return $trans->response instanceof FutureInterface ? $trans->response->wait() : $trans->response; } catch (\Exception $e) { throw RequestException::wrapException($trans->request, $e); } } }
public function testDoesNotWrapExistingRequestExceptions() { $r = new Request('GET', 'http://www.oo.com'); $e = new RequestException('foo', $r); $e2 = RequestException::wrapException($r, $e); $this->assertSame($e, $e2); }