Exemple #1
0
 /**
  * @internal
  *
  * @param array $request
  *
  * @return array
  */
 public function _invokeAsArray(array $request)
 {
     $factory = $this->factory;
     // Ensure headers are by reference. They're updated elsewhere.
     $result = $factory($request, curl_init());
     $h = $result[0];
     $hd =& $result[1];
     $body = $result[2];
     Core::doSleep($request);
     try {
         // override the default body stream with the request response
         $safecurl = new SafeCurl($h);
         $body = $safecurl->execute(Core::url($request));
     } catch (Exception $e) {
         // URL wasn't safe, return empty content
         $body = '';
         $safeCurlError = $e->getMessage();
     }
     $response = ['transfer_stats' => curl_getinfo($h)];
     $response['curl']['error'] = curl_error($h);
     $response['curl']['errno'] = curl_errno($h);
     $response['transfer_stats'] = array_merge($response['transfer_stats'], $response['curl']);
     curl_close($h);
     // override default error message in case of SafeCurl error
     if (isset($safeCurlError)) {
         $response['err_message'] = $safeCurlError;
     }
     return CurlFactory::createResponse([$this, '_invokeAsArray'], $request, $response, $hd, Stream::factory($body));
 }
Exemple #2
0
 /**
  * Get all of the received requests as a RingPHP request structure.
  *
  * @return array
  * @throws \RuntimeException
  */
 public static function received()
 {
     if (!self::$started) {
         return [];
     }
     $response = self::send('GET', '/guzzle-server/requests');
     $body = Core::body($response);
     $result = json_decode($body, true);
     if ($result === false) {
         throw new \RuntimeException('Error decoding response: ' . json_last_error());
     }
     foreach ($result as &$res) {
         if (isset($res['uri'])) {
             $res['resource'] = $res['uri'];
         }
         if (isset($res['query_string'])) {
             $res['resource'] .= '?' . $res['query_string'];
         }
         if (!isset($res['resource'])) {
             $res['resource'] = '';
         }
         // Ensure that headers are all arrays
         if (isset($res['headers'])) {
             foreach ($res['headers'] as &$h) {
                 $h = (array) $h;
             }
             unset($h);
         }
     }
     unset($res);
     return $result;
 }
 public function valid()
 {
     get_next:
     // Return true if this function has already been called for iteration.
     if ($this->currentRequest) {
         return true;
     }
     // Return false if we are at the end of the provided commands iterator.
     if (!$this->commands->valid()) {
         return false;
     }
     $command = $this->commands->current();
     if (!$command instanceof CommandInterface) {
         throw new \RuntimeException('All commands provided to the ' . __CLASS__ . ' must implement GuzzleHttp\\Command\\CommandInterface.' . ' Encountered a ' . Core::describeType($command) . ' value.');
     }
     $command->setFuture('lazy');
     $this->attachListeners($command, $this->eventListeners);
     // Prevent transfer exceptions from throwing.
     $command->getEmitter()->on('process', function (ProcessEvent $e) {
         if ($e->getException()) {
             $e->setResult(null);
         }
     }, RequestEvents::LATE);
     $builder = $this->requestBuilder;
     $result = $builder($command);
     // Skip commands that were intercepted with a result.
     if (isset($result['result'])) {
         $this->commands->next();
         goto get_next;
     }
     $this->currentRequest = $result['request'];
     return true;
 }
 public function wait()
 {
     $result = $this->parentWait();
     if (!$result instanceof ResultInterface) {
         throw new \RuntimeException('Expected a ResultInterface. Found ' . Core::describeType($result));
     }
     return $result;
 }
 public function __invoke(array $request)
 {
     Core::doSleep($request);
     $response = is_callable($this->result) ? call_user_func($this->result, $request) : $this->result;
     if (is_array($response)) {
         $response = new CompletedFutureArray($response + array('status' => null, 'body' => null, 'headers' => array(), 'reason' => null, 'effective_url' => null));
     } elseif (!$response instanceof FutureArrayInterface) {
         throw new \InvalidArgumentException('Response must be an array or FutureArrayInterface. Found ' . Core::describeType($request));
     }
     return $response;
 }
Exemple #6
0
 /**
  * @param  string $url
  *
  * @return boolean
  *
  * @throws \RuntimeException
  */
 public static function download($url)
 {
     $handler = new Ring\Client\CurlHandler();
     $response = $handler(['http_method' => 'GET', 'uri' => sprintf(':%s/%s', parse_url($url, PHP_URL_PORT), parse_url($url, PHP_URL_PATH)), 'headers' => ['scheme' => [parse_url($url, PHP_URL_SCHEME)], 'host' => [parse_url($url, PHP_URL_HOST)]]]);
     $response->wait();
     if ($response['status'] != 200) {
         throw new \RuntimeException(sprintf('%s: %s (%s)', $response['effective_url'], $response['reason'], $response['status']));
     }
     $json = Ring\Core::body($response);
     return self::load($json);
 }
 public function __invoke(array $request)
 {
     $factory = $this->factory;
     // Ensure headers are by reference. They're updated elsewhere.
     $result = $factory($request, $this->checkoutEasyHandle());
     $h = $result[0];
     $hd =& $result[1];
     $bd = $result[2];
     Core::doSleep($request);
     curl_exec($h);
     $response = ['transfer_stats' => curl_getinfo($h)];
     $response['curl']['error'] = curl_error($h);
     $response['curl']['errno'] = curl_errno($h);
     $this->releaseEasyHandle($h);
     return new CompletedFutureArray(CurlFactory::createResponse($this, $request, $response, $hd, $bd));
 }
Exemple #8
0
 public function __invoke(array $request)
 {
     Core::doSleep($request);
     $response = is_callable($this->result) ? call_user_func($this->result, $request) : $this->result;
     $data = "'" . Stream::factory($request['body']) . "'";
     $headers = '';
     foreach ($request['headers'] as $key => $val) {
         $headers .= '-H "' . $key . ': ' . $val[0] . '" ';
     }
     $exec = 'curl -X POST ' . trim($headers) . ' -d ' . $data . ' "' . $request['url'] . '"';
     $exec .= " >/dev/null 2>&1 &";
     exec($exec, $output, $return_var);
     if (is_array($response)) {
         $response = new CompletedFutureArray($response + ['status' => 200, 'body' => null, 'headers' => [], 'reason' => null, 'effective_url' => null]);
     } elseif (!$response instanceof FutureArrayInterface) {
         throw new \InvalidArgumentException('Response must be an array or FutureArrayInterface. Found ' . Core::describeType($request));
     }
     return $response;
 }
Exemple #9
0
/**
 * Fetches the HTTP URL
 *
 * @api
 * @param string $url
 * @param array $options See Guzzle Ring Request
 * @return array Ring Response
 */
function fetch($url, array $options = [])
{
    $urlComponents = parse_url($url);
    $request = [];
    $options = _default_options($options);
    if (isset($options['handler'])) {
        $handler = $options['handler'];
        unset($options['handler']);
    } else {
        $handler = default_handler();
    }
    $request = array_merge(['uri' => isset($urlComponents['path']) ? $urlComponents['path'] : '/', 'scheme' => $urlComponents['scheme']], $options);
    if (isset($urlComponents['query'])) {
        $request['query_string'] = $urlComponents['query'];
    }
    if (!Core::hasHeader($request, 'host')) {
        $host = $urlComponents['host'];
        if (isset($urlComponents['port']) && $urlComponents['port'] !== 80 && $urlComponents['port'] !== 443) {
            $host .= ':' . $urlComponents['port'];
        }
        $request['headers']['host'] = [$host];
    }
    if (!Core::hasHeader($request, 'authorization')) {
        if (isset($urlComponents['user'])) {
            $user = $urlComponents['user'];
            $password = isset($urlComponents['pass']) ? $urlComponents['pass'] : '';
        } elseif (isset($options['auth'])) {
            @(list($user, $password) = $options['auth']);
        }
        if (isset($user) && isset($password)) {
            $request['headers']['authorization'] = ['Basic ' . base64_encode($user . ':' . $password)];
        }
    }
    $response = $handler($request);
    return $response;
}
Exemple #10
0
 /**
  * Set the query part of the URL
  *
  * @param Query|string|array $query Query string value to set. Can
  *     be a string that will be parsed into a Query object, an array
  *     of key value pairs, or a Query object.
  *
  * @throws \InvalidArgumentException
  */
 public function setQuery($query)
 {
     if ($query instanceof Query) {
         $this->query = $query;
     } elseif (is_string($query)) {
         $this->query = Query::fromString($query);
     } elseif (is_array($query)) {
         $this->query = new Query($query);
     } else {
         throw new \InvalidArgumentException('Query must be a Query, ' . 'array, or string. Got ' . Core::describeType($query));
     }
 }
 private function add_debug(array $request, &$options, $value, &$params)
 {
     if ($value === false) {
         return;
     }
     static $map = array(STREAM_NOTIFY_CONNECT => 'CONNECT', STREAM_NOTIFY_AUTH_REQUIRED => 'AUTH_REQUIRED', STREAM_NOTIFY_AUTH_RESULT => 'AUTH_RESULT', STREAM_NOTIFY_MIME_TYPE_IS => 'MIME_TYPE_IS', STREAM_NOTIFY_FILE_SIZE_IS => 'FILE_SIZE_IS', STREAM_NOTIFY_REDIRECTED => 'REDIRECTED', STREAM_NOTIFY_PROGRESS => 'PROGRESS', STREAM_NOTIFY_FAILURE => 'FAILURE', STREAM_NOTIFY_COMPLETED => 'COMPLETED', STREAM_NOTIFY_RESOLVE => 'RESOLVE');
     static $args = array('severity', 'message', 'message_code', 'bytes_transferred', 'bytes_max');
     $value = Core::getDebugResource($value);
     $ident = $request['http_method'] . ' ' . Core::url($request);
     $fn = function () use($ident, $value, $map, $args) {
         $passed = func_get_args();
         $code = array_shift($passed);
         fprintf($value, '<%s> [%s] ', $ident, $map[$code]);
         foreach (array_filter($passed) as $i => $v) {
             fwrite($value, $args[$i] . ': "' . $v . '" ');
         }
         fwrite($value, "\n");
     };
     // Wrap the existing function if needed.
     $params['notification'] = isset($params['notification']) ? Core::callArray([$params['notification'], $fn]) : $fn;
 }
 public function testSupports100Continue()
 {
     Server::flush();
     Server::enqueue([['status' => '200', 'reason' => 'OK', 'headers' => ['Test' => ['Hello'], 'Content-Length' => ['4']], 'body' => 'test']]);
     $request = ['http_method' => 'PUT', 'headers' => ['Host' => [Server::$host], 'Expect' => ['100-Continue']], 'body' => 'test'];
     $handler = new StreamHandler();
     $response = $handler($request);
     $this->assertEquals(200, $response['status']);
     $this->assertEquals('OK', $response['reason']);
     $this->assertEquals(['Hello'], $response['headers']['Test']);
     $this->assertEquals(['4'], $response['headers']['Content-Length']);
     $this->assertEquals('test', Core::body($response));
 }
Exemple #13
0
 /**
  * This function ensures that a response was set on a transaction. If one
  * was not set, then the request is retried if possible. This error
  * typically means you are sending a payload, curl encountered a
  * "Connection died, retrying a fresh connect" error, tried to rewind the
  * stream, and then encountered a "necessary data rewind wasn't possible"
  * error, causing the request to be sent through curl_multi_info_read()
  * without an error status.
  */
 private static function retryFailedRewind(callable $handler, array $request, array $response)
 {
     // If there is no body, then there is some other kind of issue. This
     // is weird and should probably never happen.
     if (!isset($request['body'])) {
         $response['err_message'] = 'No response was received for a request ' . 'with no body. This could mean that you are saturating your ' . 'network.';
         return self::createErrorResponse($handler, $request, $response);
     }
     if (!Core::rewindBody($request)) {
         $response['err_message'] = 'The connection unexpectedly failed ' . 'without providing an error. The request would have been ' . 'retried, but attempting to rewind the request body failed.';
         return self::createErrorResponse($handler, $request, $response);
     }
     // Retry no more than 3 times before giving up.
     if (!isset($request['curl']['retries'])) {
         $request['curl']['retries'] = 1;
     } elseif ($request['curl']['retries'] == 2) {
         $response['err_message'] = 'The cURL request was retried 3 times ' . 'and did no succeed. cURL was unable to rewind the body of ' . 'the request and subsequent retries resulted in the same ' . 'error. Turn on the debug option to see what went wrong. ' . 'See https://bugs.php.net/bug.php?id=47204 for more information.';
         return self::createErrorResponse($handler, $request, $response);
     } else {
         $request['curl']['retries']++;
     }
     return $handler($request);
 }
Exemple #14
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());
     }
 }
Exemple #15
0
 /**
  * Adds the next request to pool and tracks what requests need to be
  * dereferenced when completing the pool.
  */
 private function addNextRequest()
 {
     if ($this->isRealized || !$this->iter || !$this->iter->valid()) {
         return false;
     }
     $request = $this->iter->current();
     $this->iter->next();
     if (!$request instanceof RequestInterface) {
         throw new \InvalidArgumentException(sprintf('All requests in the provided iterator must implement ' . 'RequestInterface. Found %s', Core::describeType($request)));
     }
     // Be sure to use "lazy" futures, meaning they do not send right away.
     $request->getConfig()->set('future', 'lazy');
     $this->attachListeners($request, $this->eventListeners);
     $response = $this->client->send($request);
     $hash = spl_object_hash($request);
     $this->waitQueue[$hash] = $response;
     // Use this function for both resolution and rejection.
     $fn = function ($value) use($request, $hash) {
         unset($this->waitQueue[$hash]);
         $result = $value instanceof ResponseInterface ? ['request' => $request, 'response' => $value, 'error' => null] : ['request' => $request, 'response' => null, 'error' => $value];
         $this->deferred->progress($result);
         $this->addNextRequest();
     };
     $response->then($fn, $fn);
     return true;
 }
Exemple #16
0
 public function testMaintainsMultiHeaderOrder()
 {
     Server::flush();
     Server::enqueue([['status' => 200, 'headers' => ['Content-Length' => ['0'], 'Foo' => ['a', 'b'], 'foo' => ['c', 'd']]]]);
     $a = new CurlMultiHandler();
     $response = $a(['http_method' => 'GET', 'headers' => ['Host' => [Server::$host]]])->wait();
     $this->assertEquals(['a', 'b', 'c', 'd'], Core::headerLines($response, 'Foo'));
 }
Exemple #17
0
 private function configureDefaults($config)
 {
     if (!isset($config['defaults'])) {
         $this->defaults = $this->getDefaultOptions();
     } else {
         $this->defaults = array_replace($this->getDefaultOptions(), $config['defaults']);
     }
     // Add the default user-agent header
     if (!isset($this->defaults['headers'])) {
         $this->defaults['headers'] = array('User-Agent' => static::getDefaultUserAgent());
     } elseif (!Core::hasHeader($this->defaults, 'User-Agent')) {
         // Add the User-Agent header if one was not already set
         $this->defaults['headers']['User-Agent'] = static::getDefaultUserAgent();
     }
 }
Exemple #18
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;
         });
     };
 }
 private function getDefaultOptions(array $request)
 {
     $headers = "";
     foreach ($request['headers'] as $name => $value) {
         foreach ((array) $value as $val) {
             $headers .= "{$name}: {$val}\r\n";
         }
     }
     $context = ['http' => ['method' => $request['http_method'], 'header' => $headers, 'protocol_version' => isset($request['version']) ? $request['version'] : 1.1, 'ignore_errors' => true, 'follow_location' => 0]];
     $body = Core::body($request);
     if (isset($body)) {
         $context['http']['content'] = $body;
         // Prevent the HTTP handler from adding a Content-Type header.
         if (!self::hasHeader($request, 'Content-Type')) {
             $context['http']['header'] .= "Content-Type:\r\n";
         }
     }
     $context['http']['header'] = rtrim($context['http']['header']);
     return $context;
 }
 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;
     };
 }
 /**
  * Throw when an invalid type is encountered.
  *
  * @param string $name     Name of the value being validated.
  * @param mixed  $provided The provided value.
  *
  * @throws \InvalidArgumentException
  */
 private function invalidType($name, $provided)
 {
     $expected = implode('|', $this->argDefinitions[$name]['valid']);
     $msg = "Invalid configuration value " . "provided for \"{$name}\". Expected {$expected}, but got " . Core::describeType($provided) . "\n\n" . $this->getArgMessage($name);
     throw new \InvalidArgumentException($msg);
 }
Exemple #22
0
 /**
  * Creates a Guzzle request object using a ring request array.
  *
  * @param array $request Ring request
  *
  * @return Request
  * @throws \InvalidArgumentException for incomplete requests.
  */
 public static function fromRingRequest(array $request)
 {
     $options = [];
     if (isset($request['version'])) {
         $options['protocol_version'] = $request['version'];
     }
     if (!isset($request['http_method'])) {
         throw new \InvalidArgumentException('No http_method');
     }
     return new Request($request['http_method'], Core::url($request), isset($request['headers']) ? $request['headers'] : [], isset($request['body']) ? Stream::factory($request['body']) : null, $options);
 }
 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;
     };
 }
Exemple #24
0
 /**
  * Set the query part of the URL.
  *
  * You may provide a query string as a string and pass $rawString as true
  * to provide a query string that is not parsed until a call to getQuery()
  * is made. Setting a raw query string will still encode invalid characters
  * in a query string.
  *
  * @param Query|string|array $query Query string value to set. Can
  *     be a string that will be parsed into a Query object, an array
  *     of key value pairs, or a Query object.
  * @param bool $rawString Set to true when providing a raw query string.
  *
  * @throws \InvalidArgumentException
  */
 public function setQuery($query, $rawString = false)
 {
     if ($query instanceof Query) {
         $this->query = $query;
     } elseif (is_string($query)) {
         if (!$rawString) {
             $this->query = Query::fromString($query);
         } else {
             // Ensure the query does not have illegal characters.
             $this->query = preg_replace_callback(self::$queryPattern, array(__CLASS__, 'encodeMatch'), $query);
         }
     } elseif (is_array($query)) {
         $this->query = new Query($query);
     } else {
         throw new \InvalidArgumentException('Query must be a Query, ' . 'array, or string. Got ' . Core::describeType($query));
     }
 }
Exemple #25
0
 public function testParsesLastResponseOnly()
 {
     $response1 = ['status' => 301, 'headers' => ['Content-Length' => ['0'], 'Location' => ['/foo']]];
     $response2 = ['status' => 200, 'headers' => ['Content-Length' => ['0'], 'Foo' => ['bar']]];
     Server::flush();
     Server::enqueue([$response1, $response2]);
     $a = new CurlMultiHandler();
     $response = $a(['http_method' => 'GET', 'headers' => ['Host' => [Server::$host]], 'client' => ['curl' => [CURLOPT_FOLLOWLOCATION => true]]])->wait();
     $this->assertEquals(1, $response['transfer_stats']['redirect_count']);
     $this->assertEquals('http://127.0.0.1:8125/foo', $response['effective_url']);
     $this->assertEquals(['bar'], $response['headers']['Foo']);
     $this->assertEquals(200, $response['status']);
     $this->assertFalse(Core::hasHeader($response, 'Location'));
 }
Exemple #26
0
 /**
  * Adds the next request to pool and tracks what requests need to be
  * dereferenced when completing the pool.
  */
 private function addNextRequest()
 {
     add_next:
     if ($this->isRealized || !$this->iter || !$this->iter->valid()) {
         return false;
     }
     $request = $this->iter->current();
     $this->iter->next();
     if (!$request instanceof RequestInterface) {
         throw new \InvalidArgumentException(sprintf('All requests in the provided iterator must implement ' . 'RequestInterface. Found %s', Core::describeType($request)));
     }
     // Be sure to use "lazy" futures, meaning they do not send right away.
     $request->getConfig()->set('future', 'lazy');
     $hash = spl_object_hash($request);
     $this->attachListeners($request, $this->eventListeners);
     $request->getEmitter()->on('before', [$this, '_trackRetries'], RequestEvents::EARLY);
     $response = $this->client->send($request);
     $this->waitQueue[$hash] = $response;
     $promise = $response->promise();
     // Don't recursively call itself for completed or rejected responses.
     if ($promise instanceof FulfilledPromise || $promise instanceof RejectedPromise) {
         try {
             $this->finishResponse($request, $response->wait(), $hash);
         } catch (\Exception $e) {
             $this->finishResponse($request, $e, $hash);
         }
         goto add_next;
     }
     // Use this function for both resolution and rejection.
     $thenFn = function ($value) use($request, $hash) {
         $this->finishResponse($request, $value, $hash);
         if (!$request->getConfig()->get('_pool_retries')) {
             $this->addNextRequests();
         }
     };
     $promise->then($thenFn, $thenFn);
     return true;
 }
Exemple #27
0
 private function checkAssociativeArray($value)
 {
     if (!is_array($value) || isset($value[0])) {
         $this->addError('must be an associative array. Found ' . Core::describeType($value));
         return false;
     }
     return true;
 }