private function wrapHandler(callable $handler, LoggerInterface $logger, LoggerInterface $tracer)
 {
     return function (array $request, Connection $connection, Transport $transport = null, $options) use($handler, $logger, $tracer) {
         $this->lastRequest = ['request' => $request];
         // Send the request using the wrapped handler.
         $response = Core::proxy($handler($request), function ($response) use($connection, $transport, $logger, $tracer, $request, $options) {
             $this->lastRequest['response'] = $response;
             if (isset($response['error'])) {
                 if ($response['error'] instanceof ConnectException || $response['error'] instanceof RingException) {
                     $this->log->warning('Curl exception encountered.');
                     $exception = $this->getCurlRetryException($request, $response);
                     $this->logRequestFail($request['http_method'], $response['effective_url'], $request['body'], $request['headers'], $response['status'], $response['body'], $response['transfer_stats']['total_time'], $exception);
                     $node = $connection->getHost();
                     $this->log->warning("Marking node {$node} dead.");
                     $connection->markDead();
                     // If the transport has not been set, we are inside a Ping or Sniff,
                     // so we don't want to retrigger retries anyway.
                     //
                     // TODO this could be handled better, but we are limited because connectionpools do not
                     // have access to Transport.  Architecturally, all of this needs to be refactored
                     if (isset($transport)) {
                         $transport->connectionPool->scheduleCheck();
                         $neverRetry = isset($request['client']['never_retry']) ? $request['client']['never_retry'] : false;
                         $shouldRetry = $transport->shouldRetry($request);
                         $shouldRetryText = $shouldRetry ? 'true' : 'false';
                         $this->log->warning("Retries left? {$shouldRetryText}");
                         if ($shouldRetry && !$neverRetry) {
                             return $transport->performRequest($request['http_method'], $request['uri'], [], $request['body'], $options);
                         }
                     }
                     $this->log->warning("Out of retries, throwing exception from {$node}");
                     // Only throw if we run out of retries
                     throw $exception;
                 } else {
                     // Something went seriously wrong, bail
                     $exception = new TransportException($response['error']->getMessage());
                     $this->logRequestFail($request['http_method'], $response['effective_url'], $request['body'], $request['headers'], $response['status'], $response['body'], $response['transfer_stats']['total_time'], $exception);
                     throw $exception;
                 }
             } else {
                 $connection->markAlive();
                 if (isset($response['body']) === true) {
                     $response['body'] = stream_get_contents($response['body']);
                     $this->lastRequest['response']['body'] = $response['body'];
                 }
                 if ($response['status'] >= 400 && $response['status'] < 500) {
                     $ignore = isset($request['client']['ignore']) ? $request['client']['ignore'] : [];
                     $this->process4xxError($request, $response, $ignore);
                 } elseif ($response['status'] >= 500) {
                     $ignore = isset($request['client']['ignore']) ? $request['client']['ignore'] : [];
                     $this->process5xxError($request, $response, $ignore);
                 }
                 // No error, deserialize
                 $response['body'] = $this->serializer->deserialize($response['body'], $response['transfer_stats']);
             }
             $this->logRequestSuccess($request['http_method'], $response['effective_url'], $request['body'], $request['headers'], $response['status'], $response['body'], $response['transfer_stats']['total_time']);
             return isset($request['client']['verbose']) && $request['client']['verbose'] === true ? $response : $response['body'];
         });
         return $response;
     };
 }
 private function wrapHandler(callable $handler, LoggerInterface $logger, LoggerInterface $tracer)
 {
     return function (array $request, Connection $connection, Transport $transport = null, $options) use($handler, $logger, $tracer) {
         $this->lastRequest = [];
         $this->lastRequest['request'] = $request;
         // Send the request using the wrapped handler.
         $response = Core::proxy($handler($request), function ($response) use($connection, $transport, $logger, $tracer, $request, $options) {
             $this->lastRequest['response'] = $response;
             if (isset($response['error']) === true) {
                 if ($response['error'] instanceof ConnectException || $response['error'] instanceof RingException) {
                     $connection->markDead();
                     $transport->connectionPool->scheduleCheck();
                     $neverRetry = isset($request['client']['never_retry']) ? $request['client']['never_retry'] : false;
                     $shouldRetry = $transport->shouldRetry($request);
                     if ($shouldRetry && !$neverRetry) {
                         return $transport->performRequest($request['http_method'], $request['uri'], [], $request['body'], $options);
                     }
                     // Due to the magic of futures, this will only be invoked if the final retry fails, since
                     // successful resolutions will go down the alternate `else` path the second time through
                     // the proxy
                     $this->throwCurlException($request, $response);
                 } else {
                     // Something went seriously wrong, bail
                     throw new TransportException($response['error']->getMessage());
                 }
             } else {
                 $connection->markAlive();
                 if (isset($response['body']) === true) {
                     $response['body'] = stream_get_contents($response['body']);
                     $this->lastRequest['response']['body'] = $response['body'];
                 }
                 if ($response['status'] >= 400 && $response['status'] < 500) {
                     $ignore = isset($request['client']['ignore']) ? $request['client']['ignore'] : [];
                     $this->process4xxError($request, $response, $ignore);
                 } elseif ($response['status'] >= 500) {
                     $ignore = isset($request['client']['ignore']) ? $request['client']['ignore'] : [];
                     $this->process5xxError($request, $response, $ignore);
                 }
                 // No error, deserialize
                 $response['body'] = $this->serializer->deserialize($response['body'], $response['transfer_stats']);
             }
             $this->logRequestSuccess($request['http_method'], $response['effective_url'], $request['body'], $request['headers'], $response['status'], $response['body'], $response['transfer_stats']['total_time']);
             return isset($request['client']['verbose']) && $request['client']['verbose'] === true ? $response : $response['body'];
         });
         return $response;
     };
 }
示例#3
0
 public function testProxiesDeferredFutureFailure()
 {
     $d = new Deferred();
     $f = new FutureArray($d->promise());
     $f2 = Core::proxy($f);
     $d->reject(new \Exception('foo'));
     try {
         $f2['hello?'];
         $this->fail('did not throw');
     } catch (\Exception $e) {
         $this->assertEquals('foo', $e->getMessage());
     }
 }
示例#4
0
 /**
  * @param callable        $handler
  * @param LoggerInterface $logger
  * @return callable
  */
 public static function processResponse(callable $handler, LoggerInterface $logger)
 {
     return function (array $request) use($handler, $logger) {
         return Core::proxy($handler($request), function (array $response) use($request, $logger) {
             // Is there any error?
             if (isset($response['error'])) {
                 $exception = new TransportException('Request failure', 0, $response['error']);
                 Logger::logState($logger, $request, $response, $exception, LogLevel::CRITICAL);
                 throw $exception;
             }
             $response['json'] = null;
             // Read body
             if (isset($response['body']) && is_resource($response['body'])) {
                 $response['body'] = stream_get_contents($response['body']);
                 // false if something wrong
                 // Extract json data
                 if ($response['body']) {
                     $response['json'] = json_decode($response['body'], true);
                     // null if something wrong
                 }
             }
             // Process errors
             if ($response['status'] >= 400) {
                 $ignore = isset($request['client']['ignore']) ? (array) $request['client']['ignore'] : [];
                 // It is possible to ignore some status codes
                 if (!in_array($response['status'], $ignore)) {
                     // Is there any message?
                     $message = isset($response['json']['message']) ? $response['json']['message'] : 'Unknown error';
                     if ($response['status'] >= 400 && $response['status'] < 500) {
                         if (404 == $response['status']) {
                             $exception = new ResourceNotFoundException();
                         } else {
                             $exception = new BadRequestException($message, $response['status']);
                         }
                     } else {
                         $exception = new ServerException($message, $response['status']);
                     }
                     Logger::logState($logger, $request, $response, $exception, LogLevel::ERROR);
                     throw $exception;
                 }
             }
             Logger::logState($logger, $request, $response);
             return $response;
         });
     };
 }