Issue #2210637 by damiankloip | Crell: Upgrade to Guzzle 4.
parent
b1eb0a2931
commit
e84971c526
|
@ -18,7 +18,7 @@
|
|||
"twig/twig": "1.15.*",
|
||||
"doctrine/common": "dev-master#a45d110f71c323e29f41eb0696fa230e3fa1b1b5",
|
||||
"doctrine/annotations": "dev-master#463d926a8dcc49271cb7db5a08364a70ed6e3cd3",
|
||||
"guzzle/http": "3.7.*",
|
||||
"guzzlehttp/guzzle": "4.0.*",
|
||||
"kriswallsmith/assetic": "1.1.*@alpha",
|
||||
"symfony-cmf/routing": "1.1.*@alpha",
|
||||
"easyrdf/easyrdf": "0.8.*",
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"This file locks the dependencies of your project to a known state",
|
||||
"Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file"
|
||||
],
|
||||
"hash": "5a96c248a0be5c8d138fcbf2a5bf9160",
|
||||
"hash": "764a98eeaf89d9f52b9c32d343036de0",
|
||||
"packages": [
|
||||
{
|
||||
"name": "doctrine/annotations",
|
||||
|
@ -457,83 +457,41 @@
|
|||
"time": "2013-12-30 22:31:37"
|
||||
},
|
||||
{
|
||||
"name": "guzzle/common",
|
||||
"version": "v3.7.1",
|
||||
"target-dir": "Guzzle/Common",
|
||||
"name": "guzzlehttp/guzzle",
|
||||
"version": "4.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/common.git",
|
||||
"reference": "v3.7.1"
|
||||
"url": "https://github.com/guzzle/guzzle.git",
|
||||
"reference": "4063f08ca434efac12bf7a3db0d370b1c451345b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/common/zipball/v3.7.1",
|
||||
"reference": "v3.7.1",
|
||||
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/4063f08ca434efac12bf7a3db0d370b1c451345b",
|
||||
"reference": "4063f08ca434efac12bf7a3db0d370b1c451345b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.2",
|
||||
"symfony/event-dispatcher": ">=2.1"
|
||||
"guzzlehttp/streams": "1.*",
|
||||
"php": ">=5.4.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-curl": "*",
|
||||
"phpunit/phpunit": "4.*",
|
||||
"psr/log": "~1"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.7-dev"
|
||||
"dev-master": "4.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Guzzle\\Common": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"description": "Common libraries used by Guzzle",
|
||||
"homepage": "http://guzzlephp.org/",
|
||||
"keywords": [
|
||||
"collection",
|
||||
"common",
|
||||
"event",
|
||||
"exception"
|
||||
],
|
||||
"time": "2013-07-05 20:17:54"
|
||||
},
|
||||
{
|
||||
"name": "guzzle/http",
|
||||
"version": "v3.7.1",
|
||||
"target-dir": "Guzzle/Http",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/http.git",
|
||||
"reference": "v3.7.1"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/http/zipball/v3.7.1",
|
||||
"reference": "v3.7.1",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"guzzle/common": "self.version",
|
||||
"guzzle/parser": "self.version",
|
||||
"guzzle/stream": "self.version",
|
||||
"php": ">=5.3.2"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-curl": "*"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.7-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Guzzle\\Http": ""
|
||||
}
|
||||
"psr-4": {
|
||||
"GuzzleHttp\\": "src/"
|
||||
},
|
||||
"files": [
|
||||
"src/functions.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
|
@ -546,93 +504,52 @@
|
|||
"homepage": "https://github.com/mtdowling"
|
||||
}
|
||||
],
|
||||
"description": "HTTP libraries used by Guzzle",
|
||||
"description": "Guzzle is a PHP HTTP client library and framework for building RESTful web service clients",
|
||||
"homepage": "http://guzzlephp.org/",
|
||||
"keywords": [
|
||||
"Guzzle",
|
||||
"client",
|
||||
"curl",
|
||||
"framework",
|
||||
"http",
|
||||
"http client"
|
||||
"http client",
|
||||
"rest",
|
||||
"web service"
|
||||
],
|
||||
"time": "2013-07-02 19:53:26"
|
||||
"time": "2014-03-29 23:11:36"
|
||||
},
|
||||
{
|
||||
"name": "guzzle/parser",
|
||||
"version": "v3.7.1",
|
||||
"target-dir": "Guzzle/Parser",
|
||||
"name": "guzzlehttp/streams",
|
||||
"version": "1.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/parser.git",
|
||||
"reference": "v3.7.1"
|
||||
"url": "https://github.com/guzzle/streams.git",
|
||||
"reference": "d249beffe5fa5e0da3855974bcc2dd9082069ccf"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/parser/zipball/v3.7.1",
|
||||
"reference": "v3.7.1",
|
||||
"url": "https://api.github.com/repos/guzzle/streams/zipball/d249beffe5fa5e0da3855974bcc2dd9082069ccf",
|
||||
"reference": "d249beffe5fa5e0da3855974bcc2dd9082069ccf",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.2"
|
||||
"php": ">=5.4.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "4.*"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.7-dev"
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Guzzle\\Parser": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"description": "Interchangeable parsers used by Guzzle",
|
||||
"homepage": "http://guzzlephp.org/",
|
||||
"keywords": [
|
||||
"URI Template",
|
||||
"cookie",
|
||||
"http",
|
||||
"message",
|
||||
"url"
|
||||
],
|
||||
"time": "2013-06-11 00:24:07"
|
||||
},
|
||||
{
|
||||
"name": "guzzle/stream",
|
||||
"version": "v3.7.1",
|
||||
"target-dir": "Guzzle/Stream",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/stream.git",
|
||||
"reference": "v3.7.1"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/stream/zipball/v3.7.1",
|
||||
"reference": "v3.7.1",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"guzzle/common": "self.version",
|
||||
"php": ">=5.3.2"
|
||||
},
|
||||
"suggest": {
|
||||
"guzzle/http": "To convert Guzzle request objects to PHP streams"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.7-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Guzzle\\Stream": ""
|
||||
}
|
||||
"psr-4": {
|
||||
"GuzzleHttp\\Stream\\": "src/"
|
||||
},
|
||||
"files": [
|
||||
"src/functions.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
|
@ -645,14 +562,13 @@
|
|||
"homepage": "https://github.com/mtdowling"
|
||||
}
|
||||
],
|
||||
"description": "Guzzle stream wrapper component",
|
||||
"description": "Provides a simple abstraction over streams of data (Guzzle 4+)",
|
||||
"homepage": "http://guzzlephp.org/",
|
||||
"keywords": [
|
||||
"Guzzle",
|
||||
"component",
|
||||
"stream"
|
||||
],
|
||||
"time": "2013-06-27 00:50:43"
|
||||
"time": "2014-03-25 18:31:28"
|
||||
},
|
||||
{
|
||||
"name": "kriswallsmith/assetic",
|
||||
|
@ -2143,9 +2059,9 @@
|
|||
"kriswallsmith/assetic": 15,
|
||||
"symfony-cmf/routing": 15
|
||||
},
|
||||
"platform": [
|
||||
|
||||
],
|
||||
"platform": {
|
||||
"php": ">=5.4.2"
|
||||
},
|
||||
"platform-dev": [
|
||||
|
||||
]
|
||||
|
|
|
@ -157,19 +157,8 @@ services:
|
|||
path.alias_manager:
|
||||
class: Drupal\Core\Path\AliasManager
|
||||
arguments: ['@path.alias_storage', '@path.alias_whitelist', '@language_manager']
|
||||
http_client_simpletest_subscriber:
|
||||
class: Drupal\Core\Http\Plugin\SimpletestHttpRequestSubscriber
|
||||
http_default_client:
|
||||
class: Guzzle\Http\Client
|
||||
# Security consideration: we must not use the certificate authority file
|
||||
# shipped with Guzzle because it can easily get outdated if a certificate
|
||||
# authority is hacked. Instead, we rely on the certificate authority file
|
||||
# provided by the operating system which is more likely going to be updated
|
||||
# in a timely fashion.
|
||||
arguments: [null, { curl.CURLOPT_TIMEOUT: 30, curl.CURLOPT_MAXREDIRS: 3, ssl.certificate_authority: system }]
|
||||
calls:
|
||||
- [addSubscriber, ['@http_client_simpletest_subscriber']]
|
||||
- [setUserAgent, ['Drupal (+http://drupal.org/)']]
|
||||
class: Drupal\Core\Http\Client
|
||||
theme.negotiator:
|
||||
class: Drupal\Core\Theme\ThemeNegotiator
|
||||
arguments: ['@access_check.theme', '@request_stack']
|
||||
|
|
|
@ -21,7 +21,7 @@ use Symfony\Component\DependencyInjection\Reference;
|
|||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
use Guzzle\Http\Exception\RequestException;
|
||||
use GuzzleHttp\Exception\RequestException;
|
||||
|
||||
/**
|
||||
* @file
|
||||
|
@ -1580,8 +1580,8 @@ function install_retrieve_file($uri, $destination) {
|
|||
}
|
||||
|
||||
try {
|
||||
$request = \Drupal::httpClient()->get($uri, array('Accept' => 'text/plain'));
|
||||
$data = $request->send()->getBody(TRUE);
|
||||
$request = \Drupal::httpClient()->get($uri, array('headers' => array('Accept' => 'text/plain')));
|
||||
$data = $request->getBody(TRUE);
|
||||
if (empty($data)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -1603,8 +1603,7 @@ function install_retrieve_file($uri, $destination) {
|
|||
*/
|
||||
function install_check_localization_server($uri) {
|
||||
try {
|
||||
$request = \Drupal::httpClient()->head($uri);
|
||||
$request->send();
|
||||
\Drupal::httpClient()->head($uri);
|
||||
return TRUE;
|
||||
}
|
||||
catch (RequestException $e) {
|
||||
|
|
|
@ -345,7 +345,7 @@ class Drupal {
|
|||
/**
|
||||
* Returns the default http client.
|
||||
*
|
||||
* @return \Guzzle\Http\ClientInterface
|
||||
* @return \GuzzleHttp\ClientInterface
|
||||
* A guzzle http client instance.
|
||||
*/
|
||||
public static function httpClient() {
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\Http\Client.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\Http;
|
||||
|
||||
use Drupal\Core\Http\Plugin\SimpletestHttpRequestSubscriber;
|
||||
use Drupal\Component\Utility\NestedArray;
|
||||
use GuzzleHttp\Client as GuzzleClient;
|
||||
|
||||
/**
|
||||
* Drupal default HTTP client class.
|
||||
*/
|
||||
class Client extends GuzzleClient {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct(array $config = []) {
|
||||
$default_config = array(
|
||||
'defaults' => array(
|
||||
'config' => array(
|
||||
'curl' => array(
|
||||
CURLOPT_TIMEOUT => 30,
|
||||
CURLOPT_MAXREDIRS => 3,
|
||||
),
|
||||
),
|
||||
// Security consideration: we must not use the certificate authority
|
||||
// file shipped with Guzzle because it can easily get outdated if a
|
||||
// certificate authority is hacked. Instead, we rely on the certificate
|
||||
// authority file provided by the operating system which is more likely
|
||||
// going to be updated in a timely fashion. This overrides the default
|
||||
// path to the pem file bundled with Guzzle.
|
||||
'verify' => TRUE,
|
||||
'headers' => array(
|
||||
'User-Agent' => 'Drupal (+http://drupal.org/)',
|
||||
),
|
||||
),
|
||||
);
|
||||
$config = NestedArray::mergeDeep($default_config, $config);
|
||||
|
||||
parent::__construct($config);
|
||||
|
||||
$this->getEmitter()->attach(new SimpletestHttpRequestSubscriber());
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains Drupal\Core\Http\Plugin\SimpletestHttpRequestSubscriber
|
||||
|
@ -6,28 +7,28 @@
|
|||
|
||||
namespace Drupal\Core\Http\Plugin;
|
||||
|
||||
use Guzzle\Common\Event;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use GuzzleHttp\Event\BeforeEvent;
|
||||
use GuzzleHttp\Event\SubscriberInterface;
|
||||
|
||||
/**
|
||||
* Subscribe to HTTP requests and override the User-Agent header if the request
|
||||
* is being dispatched from inside a simpletest.
|
||||
*/
|
||||
class SimpletestHttpRequestSubscriber implements EventSubscriberInterface {
|
||||
class SimpletestHttpRequestSubscriber implements SubscriberInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array('request.before_send' => 'onBeforeSendRequest');
|
||||
public function getEvents() {
|
||||
return array(
|
||||
'before' => array('onBeforeSendRequest'),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Event callback for request.before_send
|
||||
* Event callback for the 'before' event
|
||||
*/
|
||||
public function onBeforeSendRequest(Event $event) {
|
||||
public function onBeforeSendRequest(BeforeEvent $event) {
|
||||
// If the database prefix is being used by SimpleTest to run the tests in a copied
|
||||
// database then set the user-agent header to the database prefix so that any
|
||||
// calls to other Drupal pages will run the SimpleTest prefixed database. The
|
||||
|
@ -35,7 +36,7 @@ class SimpletestHttpRequestSubscriber implements EventSubscriberInterface {
|
|||
// same time won't interfere with each other as they would if the database
|
||||
// prefix were stored statically in a file or database variable.
|
||||
if ($test_prefix = drupal_valid_test_ua()) {
|
||||
$event['request']->setHeader('User-Agent', drupal_generate_test_ua($test_prefix));
|
||||
$event->getRequest()->setHeader('User-Agent', drupal_generate_test_ua($test_prefix));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,9 +11,8 @@ use Drupal\aggregator\FeedStorageInterface;
|
|||
use Drupal\Component\Utility\UrlHelper;
|
||||
use Drupal\Core\Form\FormBase;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Guzzle\Http\Exception\RequestException;
|
||||
use Guzzle\Http\Exception\BadResponseException;
|
||||
use Guzzle\Http\ClientInterface;
|
||||
use GuzzleHttp\Exception\RequestException;
|
||||
use GuzzleHttp\ClientInterface;
|
||||
|
||||
/**
|
||||
* Imports feeds from OPML.
|
||||
|
@ -30,7 +29,7 @@ class OpmlFeedAdd extends FormBase {
|
|||
/**
|
||||
* The HTTP client to fetch the feed data with.
|
||||
*
|
||||
* @var \Guzzle\Http\ClientInterface
|
||||
* @var \GuzzleHttp\ClientInterface
|
||||
*/
|
||||
protected $httpClient;
|
||||
|
||||
|
@ -39,7 +38,7 @@ class OpmlFeedAdd extends FormBase {
|
|||
*
|
||||
* @param \Drupal\aggregator\FeedStorageInterface $feed_storage
|
||||
* The feed storage.
|
||||
* @param \Guzzle\Http\ClientInterface $http_client
|
||||
* @param \GuzzleHttp\ClientInterface $http_client
|
||||
* The Guzzle HTTP client.
|
||||
*/
|
||||
public function __construct(FeedStorageInterface $feed_storage, ClientInterface $http_client) {
|
||||
|
@ -121,15 +120,9 @@ class OpmlFeedAdd extends FormBase {
|
|||
else {
|
||||
// @todo Move this to a fetcher implementation.
|
||||
try {
|
||||
$response = $this->httpClient->get($form_state['values']['remote'])->send();
|
||||
$response = $this->httpClient->get($form_state['values']['remote']);
|
||||
$data = $response->getBody(TRUE);
|
||||
}
|
||||
catch (BadResponseException $e) {
|
||||
$response = $e->getResponse();
|
||||
watchdog('aggregator', 'Failed to download OPML file due to "%error".', array('%error' => $response->getStatusCode() . ' ' . $response->getReasonPhrase()), WATCHDOG_WARNING);
|
||||
drupal_set_message($this->t('Failed to download OPML file due to "%error".', array('%error' => $response->getStatusCode() . ' ' . $response->getReasonPhrase())));
|
||||
return;
|
||||
}
|
||||
catch (RequestException $e) {
|
||||
watchdog('aggregator', 'Failed to download OPML file due to "%error".', array('%error' => $e->getMessage()), WATCHDOG_WARNING);
|
||||
drupal_set_message($this->t('Failed to download OPML file due to "%error".', array('%error' => $e->getMessage())));
|
||||
|
|
|
@ -10,9 +10,8 @@ namespace Drupal\aggregator\Plugin\aggregator\fetcher;
|
|||
use Drupal\aggregator\Plugin\FetcherInterface;
|
||||
use Drupal\aggregator\FeedInterface;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Guzzle\Http\ClientInterface;
|
||||
use Guzzle\Http\Exception\BadResponseException;
|
||||
use Guzzle\Http\Exception\RequestException;
|
||||
use GuzzleHttp\ClientInterface;
|
||||
use GuzzleHttp\Exception\RequestException;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
|
@ -31,14 +30,14 @@ class DefaultFetcher implements FetcherInterface, ContainerFactoryPluginInterfac
|
|||
/**
|
||||
* The HTTP client to fetch the feed data with.
|
||||
*
|
||||
* @var \Guzzle\Http\ClientInterface
|
||||
* @var \GuzzleHttp\ClientInterface
|
||||
*/
|
||||
protected $httpClient;
|
||||
|
||||
/**
|
||||
* Constructs a DefaultFetcher object.
|
||||
*
|
||||
* @param \Guzzle\Http\ClientInterface $http_client
|
||||
* @param \GuzzleHttp\ClientInterface $http_client
|
||||
* A Guzzle client object.
|
||||
*/
|
||||
public function __construct(ClientInterface $http_client) {
|
||||
|
@ -58,7 +57,7 @@ class DefaultFetcher implements FetcherInterface, ContainerFactoryPluginInterfac
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function fetch(FeedInterface $feed) {
|
||||
$request = $this->httpClient->get($feed->getUrl());
|
||||
$request = $this->httpClient->createRequest('GET', $feed->getUrl());
|
||||
$feed->source_string = FALSE;
|
||||
|
||||
// Generate conditional GET headers.
|
||||
|
@ -70,7 +69,7 @@ class DefaultFetcher implements FetcherInterface, ContainerFactoryPluginInterfac
|
|||
}
|
||||
|
||||
try {
|
||||
$response = $request->send();
|
||||
$response = $this->httpClient->send($request);
|
||||
|
||||
// In case of a 304 Not Modified, there is no new content, so return
|
||||
// FALSE.
|
||||
|
@ -79,8 +78,8 @@ class DefaultFetcher implements FetcherInterface, ContainerFactoryPluginInterfac
|
|||
}
|
||||
|
||||
$feed->source_string = $response->getBody(TRUE);
|
||||
$feed->setEtag($response->getEtag());
|
||||
$feed->setLastModified(strtotime($response->getLastModified()));
|
||||
$feed->setEtag($response->getHeader('ETag'));
|
||||
$feed->setLastModified(strtotime($response->getHeader('Last-Modified')));
|
||||
$feed->http_headers = $response->getHeaders();
|
||||
|
||||
// Update the feed URL in case of a 301 redirect.
|
||||
|
@ -90,12 +89,6 @@ class DefaultFetcher implements FetcherInterface, ContainerFactoryPluginInterfac
|
|||
}
|
||||
return TRUE;
|
||||
}
|
||||
catch (BadResponseException $e) {
|
||||
$response = $e->getResponse();
|
||||
watchdog('aggregator', 'The feed from %site seems to be broken because of error "%error".', array('%site' => $feed->label(), '%error' => $response->getStatusCode() . ' ' . $response->getReasonPhrase()), WATCHDOG_WARNING);
|
||||
drupal_set_message(t('The feed from %site seems to be broken because of error "%error".', array('%site' => $feed->label(), '%error' => $response->getStatusCode() . ' ' . $response->getReasonPhrase())));
|
||||
return FALSE;
|
||||
}
|
||||
catch (RequestException $e) {
|
||||
watchdog('aggregator', 'The feed from %site seems to be broken because of error "%error".', array('%site' => $feed->label(), '%error' => $e->getMessage()), WATCHDOG_WARNING);
|
||||
drupal_set_message(t('The feed from %site seems to be broken because of error "%error".', array('%site' => $feed->label(), '%error' => $e->getMessage())));
|
||||
|
|
|
@ -10,7 +10,6 @@ namespace Drupal\aggregator_test\Plugin\aggregator\fetcher;
|
|||
use Drupal\aggregator\Plugin\FetcherInterface;
|
||||
use Drupal\aggregator\Plugin\aggregator\fetcher\DefaultFetcher;
|
||||
use Drupal\aggregator\FeedInterface;
|
||||
use Guzzle\Http\Exception\BadResponseException;
|
||||
|
||||
/**
|
||||
* Defines a test fetcher implementation.
|
||||
|
|
|
@ -10,7 +10,7 @@ namespace Drupal\hal\Normalizer;
|
|||
use Drupal\Core\Entity\EntityManagerInterface;
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
use Drupal\rest\LinkManager\LinkManagerInterface;
|
||||
use Guzzle\Http\ClientInterface;
|
||||
use GuzzleHttp\ClientInterface;
|
||||
|
||||
/**
|
||||
* Converts the Drupal entity object structure to a HAL array structure.
|
||||
|
@ -27,7 +27,7 @@ class FileEntityNormalizer extends ContentEntityNormalizer {
|
|||
/**
|
||||
* The HTTP client.
|
||||
*
|
||||
* @var \Guzzle\Http\ClientInterface
|
||||
* @var \GuzzleHttp\ClientInterface
|
||||
*/
|
||||
protected $httpClient;
|
||||
|
||||
|
@ -36,7 +36,7 @@ class FileEntityNormalizer extends ContentEntityNormalizer {
|
|||
*
|
||||
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
|
||||
* The entity manager.
|
||||
* @param \Guzzle\Http\ClientInterface $http_client
|
||||
* @param \GuzzleHttp\ClientInterface $http_client
|
||||
* The HTTP Client.
|
||||
* @param \Drupal\rest\LinkManager\LinkManagerInterface $link_manager
|
||||
* The hypermedia link manager.
|
||||
|
@ -64,9 +64,7 @@ class FileEntityNormalizer extends ContentEntityNormalizer {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function denormalize($data, $class, $format = NULL, array $context = array()) {
|
||||
$file_data = $this->httpClient->get($data['uri'][0]['value'])
|
||||
->send()
|
||||
->getBody(TRUE);
|
||||
$file_data = $this->httpClient->get($data['uri'][0]['value'])->getBody(TRUE);
|
||||
|
||||
$path = 'temporary://' . drupal_basename($data['uri'][0]['value']);
|
||||
$data['uri'] = file_unmanaged_save_data($file_data, $path);
|
||||
|
|
|
@ -5,8 +5,7 @@
|
|||
* Batch process to check the availability of remote or local po files.
|
||||
*/
|
||||
|
||||
use Guzzle\Http\Exception\BadResponseException;
|
||||
use Guzzle\Http\Exception\RequestException;
|
||||
use GuzzleHttp\Exception\RequestException;
|
||||
|
||||
/**
|
||||
* Load the common translation API.
|
||||
|
@ -231,9 +230,7 @@ function locale_translation_batch_fetch_finished($success, $results) {
|
|||
function locale_translation_http_check($uri) {
|
||||
|
||||
try {
|
||||
$response = \Drupal::httpClient()
|
||||
->head($uri)
|
||||
->send();
|
||||
$response = \Drupal::httpClient()->head($uri);
|
||||
$result = array();
|
||||
|
||||
// Return the effective URL if it differs from the requested.
|
||||
|
@ -241,10 +238,10 @@ function locale_translation_http_check($uri) {
|
|||
$result['location'] = $response->getEffectiveUrl();
|
||||
}
|
||||
|
||||
$result['last_modified'] = $response->getLastModified() ? strtotime($response->getLastModified()) : 0;
|
||||
$result['last_modified'] = $response->hasHeader('Last-Modified') ? strtotime($response->getHeader('Last-Modified')) : 0;
|
||||
return $result;
|
||||
}
|
||||
catch (BadResponseException $e) {
|
||||
catch (RequestException $e) {
|
||||
// Handle 4xx and 5xx http responses.
|
||||
$response = $e->getResponse();
|
||||
if ($response->getStatusCode() == 404) {
|
||||
|
@ -258,11 +255,7 @@ function locale_translation_http_check($uri) {
|
|||
}
|
||||
watchdog('locale', 'HTTP request to @url failed with error: @error.', array('@url' => $uri, '@error' => $response->getStatusCode() . ' ' . $response->getReasonPhrase()));
|
||||
}
|
||||
catch (RequestException $e) {
|
||||
// Handle connection problems and cURL specific errors (CurlException) and
|
||||
// other http related errors.
|
||||
watchdog('locale', 'HTTP request to @url failed with error: @error.', array('@url' => $uri, '@error' => $e->getMessage()));
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ class StatisticsAdminTest extends WebTestBase {
|
|||
/**
|
||||
* The Guzzle HTTP client.
|
||||
*
|
||||
* @var \Guzzle\Http\ClientInterface;
|
||||
* @var \GuzzleHttp\ClientInterface;
|
||||
*/
|
||||
protected $client;
|
||||
|
||||
|
@ -63,7 +63,7 @@ class StatisticsAdminTest extends WebTestBase {
|
|||
$this->drupalLogin($this->privileged_user);
|
||||
$this->test_node = $this->drupalCreateNode(array('type' => 'page', 'uid' => $this->privileged_user->id()));
|
||||
$this->client = \Drupal::httpClient();
|
||||
$this->client->setConfig(array('curl.options' => array(CURLOPT_TIMEOUT => 10)));
|
||||
$this->client->setDefaultOption('config/curl', array(CURLOPT_TIMEOUT => 10));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -86,16 +86,16 @@ class StatisticsAdminTest extends WebTestBase {
|
|||
$post = array('nid' => $nid);
|
||||
global $base_url;
|
||||
$stats_path = $base_url . '/' . drupal_get_path('module', 'statistics'). '/statistics.php';
|
||||
$this->client->post($stats_path, array(), $post)->send();
|
||||
$this->client->post($stats_path, array('body' => $post));
|
||||
|
||||
// Hit the node again (the counter is incremented after the hit, so
|
||||
// "1 view" will actually be shown when the node is hit the second time).
|
||||
$this->drupalGet('node/' . $this->test_node->id());
|
||||
$this->client->post($stats_path, array(), $post)->send();
|
||||
$this->client->post($stats_path, array('body' => $post));
|
||||
$this->assertText('1 view', 'Node is viewed once.');
|
||||
|
||||
$this->drupalGet('node/' . $this->test_node->id());
|
||||
$this->client->post($stats_path, array(), $post)->send();
|
||||
$this->client->post($stats_path, array('body' => $post));
|
||||
$this->assertText('2 views', 'Node is viewed 2 times.');
|
||||
}
|
||||
|
||||
|
@ -111,7 +111,7 @@ class StatisticsAdminTest extends WebTestBase {
|
|||
$post = array('nid' => $nid);
|
||||
global $base_url;
|
||||
$stats_path = $base_url . '/' . drupal_get_path('module', 'statistics'). '/statistics.php';
|
||||
$this->client->post($stats_path, array(), $post)->send();
|
||||
$this->client->post($stats_path, array('body' => $post));
|
||||
|
||||
$result = db_select('node_counter', 'n')
|
||||
->fields('n', array('nid'))
|
||||
|
@ -145,9 +145,9 @@ class StatisticsAdminTest extends WebTestBase {
|
|||
$post = array('nid' => $nid);
|
||||
global $base_url;
|
||||
$stats_path = $base_url . '/' . drupal_get_path('module', 'statistics'). '/statistics.php';
|
||||
$this->client->post($stats_path, array(), $post)->send();
|
||||
$this->client->post($stats_path, array('body' => $post));
|
||||
$this->drupalGet('node/' . $this->test_node->id());
|
||||
$this->client->post($stats_path, array(), $post)->send();
|
||||
$this->client->post($stats_path, array('body' => $post));
|
||||
$this->assertText('1 view', 'Node is viewed once.');
|
||||
|
||||
// statistics_cron() will subtract
|
||||
|
|
|
@ -27,7 +27,7 @@ class StatisticsLoggingTest extends WebTestBase {
|
|||
/**
|
||||
* The Guzzle HTTP client.
|
||||
*
|
||||
* @var \Guzzle\Http\ClientInterface;
|
||||
* @var \GuzzleHttp\ClientInterface;
|
||||
*/
|
||||
protected $client;
|
||||
|
||||
|
@ -61,7 +61,7 @@ class StatisticsLoggingTest extends WebTestBase {
|
|||
db_truncate('node_counter');
|
||||
|
||||
$this->client = \Drupal::httpClient();
|
||||
$this->client->setConfig(array('curl.options' => array(CURLOPT_TIMEOUT => 10)));
|
||||
$this->client->setDefaultOption('config/curl', array(CURLOPT_TIMEOUT => 10));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -93,7 +93,7 @@ class StatisticsLoggingTest extends WebTestBase {
|
|||
// Manually call statistics.php to simulate ajax data collection behavior.
|
||||
$nid = $this->node->id();
|
||||
$post = array('nid' => $nid);
|
||||
$this->client->post($stats_path, array(), $post)->send();
|
||||
$this->client->post($stats_path, array('body' => $post));
|
||||
$node_counter = statistics_get($this->node->id());
|
||||
$this->assertIdentical($node_counter['totalcount'], '1');
|
||||
}
|
||||
|
|
|
@ -37,8 +37,8 @@ class StatisticsReportsTest extends StatisticsTestBase {
|
|||
global $base_url;
|
||||
$stats_path = $base_url . '/' . drupal_get_path('module', 'statistics'). '/statistics.php';
|
||||
$client = \Drupal::httpClient();
|
||||
$client->setConfig(array('curl.options' => array(CURLOPT_TIMEOUT => 10)));
|
||||
$client->post($stats_path, $headers, $post)->send();
|
||||
$client->setDefaultOption('config/curl', array(CURLOPT_TIMEOUT => 10));
|
||||
$client->post($stats_path, array('headers' => $headers, 'body' => $post));
|
||||
|
||||
// Configure and save the block.
|
||||
$this->drupalPlaceBlock('statistics_popular_block', array(
|
||||
|
|
|
@ -41,8 +41,8 @@ class StatisticsTokenReplaceTest extends StatisticsTestBase {
|
|||
global $base_url;
|
||||
$stats_path = $base_url . '/' . drupal_get_path('module', 'statistics'). '/statistics.php';
|
||||
$client = \Drupal::httpClient();
|
||||
$client->setConfig(array('curl.options' => array(CURLOPT_TIMEOUT => 10)));
|
||||
$client->post($stats_path, $headers, $post)->send();
|
||||
$client->setDefaultOption('config/curl', array(CURLOPT_TIMEOUT => 10));
|
||||
$client->post($stats_path, array('headers' => $headers, 'body' => $post));
|
||||
$statistics = statistics_get($node->id());
|
||||
|
||||
// Generate and test tokens.
|
||||
|
|
|
@ -83,8 +83,8 @@ class IntegrationTest extends ViewTestBase {
|
|||
global $base_url;
|
||||
$stats_path = $base_url . '/' . drupal_get_path('module', 'statistics'). '/statistics.php';
|
||||
$client = \Drupal::httpClient();
|
||||
$client->setConfig(array('curl.options' => array(CURLOPT_TIMEOUT => 10)));
|
||||
$client->post($stats_path, array(), array('nid' => $this->node->id()))->send();
|
||||
$client->setDefaultOption('config/curl', array(CURLOPT_TIMEOUT => 10));
|
||||
$client->post($stats_path, array('body' => array('nid' => $this->node->id())));
|
||||
$this->drupalGet('test_statistics_integration');
|
||||
|
||||
$expected = statistics_get($this->node->id());
|
||||
|
|
|
@ -12,8 +12,7 @@ use Drupal\Core\Extension\ExtensionDiscovery;
|
|||
use Drupal\block\BlockPluginInterface;
|
||||
use Drupal\user\UserInterface;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Guzzle\Http\Exception\BadResponseException;
|
||||
use Guzzle\Http\Exception\RequestException;
|
||||
use GuzzleHttp\Exception\RequestException;
|
||||
|
||||
/**
|
||||
* Maximum age of temporary files in seconds.
|
||||
|
@ -1677,15 +1676,9 @@ function system_retrieve_file($url, $destination = NULL, $managed = FALSE, $repl
|
|||
try {
|
||||
$data = \Drupal::httpClient()
|
||||
->get($url)
|
||||
->send()
|
||||
->getBody(TRUE);
|
||||
$local = $managed ? file_save_data($data, $path, $replace) : file_unmanaged_save_data($data, $path, $replace);
|
||||
}
|
||||
catch (BadResponseException $exception) {
|
||||
$response = $exception->getResponse();
|
||||
drupal_set_message(t('Failed to fetch file due to HTTP error "%error"', array('%error' => $response->getStatusCode() . ' ' . $response->getReasonPhrase())), 'error');
|
||||
return FALSE;
|
||||
}
|
||||
catch (RequestException $exception) {
|
||||
drupal_set_message(t('Failed to fetch file due to error "%error"', array('%error' => $exception->getMessage())), 'error');
|
||||
return FALSE;
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
namespace Drupal\update;
|
||||
|
||||
use Drupal\Core\Config\ConfigFactoryInterface;
|
||||
use Guzzle\Http\ClientInterface;
|
||||
use Guzzle\Http\Exception\RequestException;
|
||||
use GuzzleHttp\ClientInterface;
|
||||
use GuzzleHttp\Exception\RequestException;
|
||||
|
||||
/**
|
||||
* Fetches project information from remote locations.
|
||||
|
@ -38,7 +38,7 @@ class UpdateFetcher implements UpdateFetcherInterface {
|
|||
/**
|
||||
* The HTTP client to fetch the feed data with.
|
||||
*
|
||||
* @var \Guzzle\Http\ClientInterface
|
||||
* @var \GuzzleHttp\ClientInterface
|
||||
*/
|
||||
protected $httpClient;
|
||||
|
||||
|
@ -47,7 +47,7 @@ class UpdateFetcher implements UpdateFetcherInterface {
|
|||
*
|
||||
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
|
||||
* The config factory.
|
||||
* @param \Guzzle\Http\ClientInterface $http_client
|
||||
* @param \GuzzleHttp\ClientInterface $http_client
|
||||
* A Guzzle client object.
|
||||
*/
|
||||
public function __construct(ConfigFactoryInterface $config_factory, ClientInterface $http_client) {
|
||||
|
@ -64,8 +64,7 @@ class UpdateFetcher implements UpdateFetcherInterface {
|
|||
$data = '';
|
||||
try {
|
||||
$data = $this->httpClient
|
||||
->get($url, array('Accept' => 'text/xml'))
|
||||
->send()
|
||||
->get($url, array('headers' => array('Accept' => 'text/xml')))
|
||||
->getBody(TRUE);
|
||||
}
|
||||
catch (RequestException $exception) {
|
||||
|
|
|
@ -39,7 +39,10 @@ class UpdateFetcherTest extends UnitTestCase {
|
|||
*/
|
||||
protected function setUp() {
|
||||
$config_factory = $this->getConfigFactoryStub(array('update.settings' => array('fetch_url' => 'http://www.example.com')));
|
||||
$this->updateFetcher = new UpdateFetcher($config_factory, $this->getMock('Guzzle\Http\Client'));
|
||||
$http_client_mock = $this->getMockBuilder('Drupal\Core\Http\Client')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$this->updateFetcher = new UpdateFetcher($config_factory, $http_client_mock);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -11,8 +11,7 @@
|
|||
* This version is made available under the GNU GPL License
|
||||
*/
|
||||
|
||||
use Guzzle\Http\Exception\BadResponseException;
|
||||
use Guzzle\Http\Exception\RequestException;
|
||||
use GuzzleHttp\Exception\RequestException;
|
||||
|
||||
/**
|
||||
* Turns a data structure into objects with 'data' and 'type' attributes.
|
||||
|
@ -561,15 +560,11 @@ function _xmlrpc($url, array $args, array $headers = array()) {
|
|||
$args = $args[$method];
|
||||
}
|
||||
$xmlrpc_request = xmlrpc_request($method, $args);
|
||||
$request = \Drupal::httpClient()->post($url, $headers, $xmlrpc_request->xml);
|
||||
$request->setHeader('Content-Type', 'text/xml');
|
||||
|
||||
$headers['Content-Type'] = 'text/xml';
|
||||
|
||||
try {
|
||||
$response = $request->send();
|
||||
}
|
||||
catch (BadResponseException $exception) {
|
||||
$response = $exception->getResponse();
|
||||
xmlrpc_error($response->getStatusCode(), $response->getReasonPhrase());
|
||||
return FALSE;
|
||||
$response = \Drupal::httpClient()->post($url, array('headers' => $headers, 'body' => $xmlrpc_request->xml));
|
||||
}
|
||||
catch (RequestException $exception) {
|
||||
xmlrpc_error(NULL, $exception->getMethod());
|
||||
|
|
|
@ -9,6 +9,7 @@ namespace Drupal\Tests\Core\Cache;
|
|||
|
||||
use Drupal\Core\Cache\CacheContexts;
|
||||
use Drupal\Core\Cache\CacheContextInterface;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* Fake cache context class.
|
||||
|
@ -38,7 +39,7 @@ class FooCacheContext implements CacheContextInterface {
|
|||
*
|
||||
* @see \Drupal\Core\Cache\CacheContexts
|
||||
*/
|
||||
class CacheContextsTest extends \PHPUnit_Framework_TestCase {
|
||||
class CacheContextsTest extends UnitTestCase {
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
|
|
|
@ -291,8 +291,25 @@ class ClassLoader
|
|||
return $this->classMap[$class];
|
||||
}
|
||||
|
||||
$file = $this->findFileWithExtension($class, '.php');
|
||||
|
||||
// Search for Hack files if we are running on HHVM
|
||||
if ($file === null && defined('HHVM_VERSION')) {
|
||||
$file = $this->findFileWithExtension($class, '.hh');
|
||||
}
|
||||
|
||||
if ($file === null) {
|
||||
// Remember that this class does not exist.
|
||||
return $this->classMap[$class] = false;
|
||||
}
|
||||
|
||||
return $file;
|
||||
}
|
||||
|
||||
private function findFileWithExtension($class, $ext)
|
||||
{
|
||||
// PSR-4 lookup
|
||||
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . '.php';
|
||||
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
|
||||
|
||||
$first = $class[0];
|
||||
if (isset($this->prefixLengthsPsr4[$first])) {
|
||||
|
@ -321,7 +338,7 @@ class ClassLoader
|
|||
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
|
||||
} else {
|
||||
// PEAR-like class name
|
||||
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . '.php';
|
||||
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
|
||||
}
|
||||
|
||||
if (isset($this->prefixesPsr0[$first])) {
|
||||
|
@ -347,9 +364,6 @@ class ClassLoader
|
|||
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
|
||||
// Remember that this class does not exist.
|
||||
return $this->classMap[$class] = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,8 @@ $vendorDir = dirname(dirname(__FILE__));
|
|||
$baseDir = dirname(dirname($vendorDir));
|
||||
|
||||
return array(
|
||||
$vendorDir . '/guzzlehttp/streams/src/functions.php',
|
||||
$vendorDir . '/kriswallsmith/assetic/src/functions.php',
|
||||
$vendorDir . '/guzzlehttp/guzzle/src/functions.php',
|
||||
$baseDir . '/core/lib/Drupal.php',
|
||||
);
|
||||
|
|
|
@ -25,10 +25,6 @@ return array(
|
|||
'Symfony\\Component\\ClassLoader\\' => array($vendorDir . '/symfony/class-loader'),
|
||||
'Symfony\\Cmf\\Component\\Routing' => array($vendorDir . '/symfony-cmf/routing'),
|
||||
'Psr\\Log\\' => array($vendorDir . '/psr/log'),
|
||||
'Guzzle\\Stream' => array($vendorDir . '/guzzle/stream'),
|
||||
'Guzzle\\Parser' => array($vendorDir . '/guzzle/parser'),
|
||||
'Guzzle\\Http' => array($vendorDir . '/guzzle/http'),
|
||||
'Guzzle\\Common' => array($vendorDir . '/guzzle/common'),
|
||||
'Gliph' => array($vendorDir . '/sdboyer/gliph/src'),
|
||||
'EasyRdf_' => array($vendorDir . '/easyrdf/easyrdf/lib'),
|
||||
'Drupal\\Driver' => array($baseDir . '/drivers/lib'),
|
||||
|
|
|
@ -6,4 +6,6 @@ $vendorDir = dirname(dirname(__FILE__));
|
|||
$baseDir = dirname(dirname($vendorDir));
|
||||
|
||||
return array(
|
||||
'GuzzleHttp\\Stream\\' => array($vendorDir . '/guzzlehttp/streams/src'),
|
||||
'GuzzleHttp\\' => array($vendorDir . '/guzzlehttp/guzzle/src'),
|
||||
);
|
||||
|
|
|
@ -2199,5 +2199,123 @@
|
|||
],
|
||||
"description": "Symfony Yaml Component",
|
||||
"homepage": "http://symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/streams",
|
||||
"version": "1.0.0",
|
||||
"version_normalized": "1.0.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/streams.git",
|
||||
"reference": "d249beffe5fa5e0da3855974bcc2dd9082069ccf"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/streams/zipball/d249beffe5fa5e0da3855974bcc2dd9082069ccf",
|
||||
"reference": "d249beffe5fa5e0da3855974bcc2dd9082069ccf",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.4.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "4.*"
|
||||
},
|
||||
"time": "2014-03-25 18:31:28",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"GuzzleHttp\\Stream\\": "src/"
|
||||
},
|
||||
"files": [
|
||||
"src/functions.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Michael Dowling",
|
||||
"email": "mtdowling@gmail.com",
|
||||
"homepage": "https://github.com/mtdowling"
|
||||
}
|
||||
],
|
||||
"description": "Provides a simple abstraction over streams of data (Guzzle 4+)",
|
||||
"homepage": "http://guzzlephp.org/",
|
||||
"keywords": [
|
||||
"Guzzle",
|
||||
"stream"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/guzzle",
|
||||
"version": "4.0.0",
|
||||
"version_normalized": "4.0.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/guzzle.git",
|
||||
"reference": "4063f08ca434efac12bf7a3db0d370b1c451345b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/4063f08ca434efac12bf7a3db0d370b1c451345b",
|
||||
"reference": "4063f08ca434efac12bf7a3db0d370b1c451345b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"guzzlehttp/streams": "1.*",
|
||||
"php": ">=5.4.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-curl": "*",
|
||||
"phpunit/phpunit": "4.*",
|
||||
"psr/log": "~1"
|
||||
},
|
||||
"time": "2014-03-29 23:11:36",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "4.0.x-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"GuzzleHttp\\": "src/"
|
||||
},
|
||||
"files": [
|
||||
"src/functions.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Michael Dowling",
|
||||
"email": "mtdowling@gmail.com",
|
||||
"homepage": "https://github.com/mtdowling"
|
||||
}
|
||||
],
|
||||
"description": "Guzzle is a PHP HTTP client library and framework for building RESTful web service clients",
|
||||
"homepage": "http://guzzlephp.org/",
|
||||
"keywords": [
|
||||
"client",
|
||||
"curl",
|
||||
"framework",
|
||||
"http",
|
||||
"http client",
|
||||
"rest",
|
||||
"web service"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
|
@ -1,49 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Common;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
/**
|
||||
* Class that holds an event dispatcher
|
||||
*/
|
||||
class AbstractHasDispatcher implements HasDispatcherInterface
|
||||
{
|
||||
/** @var EventDispatcherInterface */
|
||||
protected $eventDispatcher;
|
||||
|
||||
public static function getAllEvents()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
public function setEventDispatcher(EventDispatcherInterface $eventDispatcher)
|
||||
{
|
||||
$this->eventDispatcher = $eventDispatcher;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getEventDispatcher()
|
||||
{
|
||||
if (!$this->eventDispatcher) {
|
||||
$this->eventDispatcher = new EventDispatcher();
|
||||
}
|
||||
|
||||
return $this->eventDispatcher;
|
||||
}
|
||||
|
||||
public function dispatch($eventName, array $context = array())
|
||||
{
|
||||
$this->getEventDispatcher()->dispatch($eventName, new Event($context));
|
||||
}
|
||||
|
||||
public function addSubscriber(EventSubscriberInterface $subscriber)
|
||||
{
|
||||
$this->getEventDispatcher()->addSubscriber($subscriber);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
|
@ -1,403 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Common;
|
||||
|
||||
use Guzzle\Common\Exception\InvalidArgumentException;
|
||||
use Guzzle\Common\Exception\RuntimeException;
|
||||
|
||||
/**
|
||||
* Key value pair collection object
|
||||
*/
|
||||
class Collection implements \ArrayAccess, \IteratorAggregate, \Countable, ToArrayInterface
|
||||
{
|
||||
/** @var array Data associated with the object. */
|
||||
protected $data;
|
||||
|
||||
/**
|
||||
* @param array $data Associative array of data to set
|
||||
*/
|
||||
public function __construct(array $data = array())
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new collection from an array, validate the keys, and add default values where missing
|
||||
*
|
||||
* @param array $config Configuration values to apply.
|
||||
* @param array $defaults Default parameters
|
||||
* @param array $required Required parameter names
|
||||
*
|
||||
* @return self
|
||||
* @throws InvalidArgumentException if a parameter is missing
|
||||
*/
|
||||
public static function fromConfig(array $config = array(), array $defaults = array(), array $required = array())
|
||||
{
|
||||
$data = $config + $defaults;
|
||||
|
||||
if ($missing = array_diff($required, array_keys($data))) {
|
||||
throw new InvalidArgumentException('Config is missing the following keys: ' . implode(', ', $missing));
|
||||
}
|
||||
|
||||
return new self($data);
|
||||
}
|
||||
|
||||
public function count()
|
||||
{
|
||||
return count($this->data);
|
||||
}
|
||||
|
||||
public function getIterator()
|
||||
{
|
||||
return new \ArrayIterator($this->data);
|
||||
}
|
||||
|
||||
public function toArray()
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all key value pairs
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
$this->data = array();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all or a subset of matching key value pairs
|
||||
*
|
||||
* @param array $keys Pass an array of keys to retrieve only a subset of key value pairs
|
||||
*
|
||||
* @return array Returns an array of all matching key value pairs
|
||||
*/
|
||||
public function getAll(array $keys = null)
|
||||
{
|
||||
return $keys ? array_intersect_key($this->data, array_flip($keys)) : $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a specific key value.
|
||||
*
|
||||
* @param string $key Key to retrieve.
|
||||
*
|
||||
* @return mixed|null Value of the key or NULL
|
||||
*/
|
||||
public function get($key)
|
||||
{
|
||||
return isset($this->data[$key]) ? $this->data[$key] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a key value pair
|
||||
*
|
||||
* @param string $key Key to set
|
||||
* @param mixed $value Value to set
|
||||
*
|
||||
* @return Collection Returns a reference to the object
|
||||
*/
|
||||
public function set($key, $value)
|
||||
{
|
||||
$this->data[$key] = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a value to a key. If a key of the same name has already been added, the key value will be converted into an
|
||||
* array and the new value will be pushed to the end of the array.
|
||||
*
|
||||
* @param string $key Key to add
|
||||
* @param mixed $value Value to add to the key
|
||||
*
|
||||
* @return Collection Returns a reference to the object.
|
||||
*/
|
||||
public function add($key, $value)
|
||||
{
|
||||
if (!array_key_exists($key, $this->data)) {
|
||||
$this->data[$key] = $value;
|
||||
} elseif (is_array($this->data[$key])) {
|
||||
$this->data[$key][] = $value;
|
||||
} else {
|
||||
$this->data[$key] = array($this->data[$key], $value);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a specific key value pair
|
||||
*
|
||||
* @param string $key A key to remove
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function remove($key)
|
||||
{
|
||||
unset($this->data[$key]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all keys in the collection
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getKeys()
|
||||
{
|
||||
return array_keys($this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the specified key is present.
|
||||
*
|
||||
* @param string $key The key for which to check the existence.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasKey($key)
|
||||
{
|
||||
return array_key_exists($key, $this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Case insensitive search the keys in the collection
|
||||
*
|
||||
* @param string $key Key to search for
|
||||
*
|
||||
* @return bool|string Returns false if not found, otherwise returns the key
|
||||
*/
|
||||
public function keySearch($key)
|
||||
{
|
||||
foreach (array_keys($this->data) as $k) {
|
||||
if (!strcasecmp($k, $key)) {
|
||||
return $k;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if any keys contains a certain value
|
||||
*
|
||||
* @param string $value Value to search for
|
||||
*
|
||||
* @return mixed Returns the key if the value was found FALSE if the value was not found.
|
||||
*/
|
||||
public function hasValue($value)
|
||||
{
|
||||
return array_search($value, $this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the data of the object with the value of an array
|
||||
*
|
||||
* @param array $data Associative array of data
|
||||
*
|
||||
* @return Collection Returns a reference to the object
|
||||
*/
|
||||
public function replace(array $data)
|
||||
{
|
||||
$this->data = $data;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add and merge in a Collection or array of key value pair data.
|
||||
*
|
||||
* @param Collection|array $data Associative array of key value pair data
|
||||
*
|
||||
* @return Collection Returns a reference to the object.
|
||||
*/
|
||||
public function merge($data)
|
||||
{
|
||||
foreach ($data as $key => $value) {
|
||||
$this->add($key, $value);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Over write key value pairs in this collection with all of the data from an array or collection.
|
||||
*
|
||||
* @param array|\Traversable $data Values to override over this config
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function overwriteWith($data)
|
||||
{
|
||||
if (is_array($data)) {
|
||||
$this->data = $data + $this->data;
|
||||
} elseif ($data instanceof Collection) {
|
||||
$this->data = $data->toArray() + $this->data;
|
||||
} else {
|
||||
foreach ($data as $key => $value) {
|
||||
$this->data[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Collection containing all the elements of the collection after applying the callback function to each
|
||||
* one. The Closure should accept three parameters: (string) $key, (string) $value, (array) $context and return a
|
||||
* modified value
|
||||
*
|
||||
* @param \Closure $closure Closure to apply
|
||||
* @param array $context Context to pass to the closure
|
||||
* @param bool $static Set to TRUE to use the same class as the return rather than returning a Collection
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function map(\Closure $closure, array $context = array(), $static = true)
|
||||
{
|
||||
$collection = $static ? new static() : new self();
|
||||
foreach ($this as $key => $value) {
|
||||
$collection->add($key, $closure($key, $value, $context));
|
||||
}
|
||||
|
||||
return $collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates over each key value pair in the collection passing them to the Closure. If the Closure function returns
|
||||
* true, the current value from input is returned into the result Collection. The Closure must accept three
|
||||
* parameters: (string) $key, (string) $value and return Boolean TRUE or FALSE for each value.
|
||||
*
|
||||
* @param \Closure $closure Closure evaluation function
|
||||
* @param bool $static Set to TRUE to use the same class as the return rather than returning a Collection
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function filter(\Closure $closure, $static = true)
|
||||
{
|
||||
$collection = ($static) ? new static() : new self();
|
||||
foreach ($this->data as $key => $value) {
|
||||
if ($closure($key, $value)) {
|
||||
$collection->add($key, $value);
|
||||
}
|
||||
}
|
||||
|
||||
return $collection;
|
||||
}
|
||||
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
return isset($this->data[$offset]);
|
||||
}
|
||||
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
return isset($this->data[$offset]) ? $this->data[$offset] : null;
|
||||
}
|
||||
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
$this->data[$offset] = $value;
|
||||
}
|
||||
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
unset($this->data[$offset]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a value into a nested array key. Keys will be created as needed to set the value.
|
||||
*
|
||||
* @param string $path Path to set
|
||||
* @param mixed $value Value to set at the key
|
||||
*
|
||||
* @return self
|
||||
* @throws RuntimeException when trying to setPath using a nested path that travels through a scalar value
|
||||
*/
|
||||
public function setPath($path, $value)
|
||||
{
|
||||
$current =& $this->data;
|
||||
$queue = explode('/', $path);
|
||||
while (null !== ($key = array_shift($queue))) {
|
||||
if (!is_array($current)) {
|
||||
throw new RuntimeException("Trying to setPath {$path}, but {$key} is set and is not an array");
|
||||
} elseif (!$queue) {
|
||||
$current[$key] = $value;
|
||||
} elseif (isset($current[$key])) {
|
||||
$current =& $current[$key];
|
||||
} else {
|
||||
$current[$key] = array();
|
||||
$current =& $current[$key];
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a value from the collection using an array path (e.g. foo/baz/bar would retrieve bar from two nested arrays)
|
||||
* Allows for wildcard searches which recursively combine matches up to the level at which the wildcard occurs. This
|
||||
* can be useful for accepting any key of a sub-array and combining matching keys from each diverging path.
|
||||
*
|
||||
* @param string $path Path to traverse and retrieve a value from
|
||||
* @param string $separator Character used to add depth to the search
|
||||
* @param mixed $data Optional data to descend into (used when wildcards are encountered)
|
||||
*
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function getPath($path, $separator = '/', $data = null)
|
||||
{
|
||||
if ($data === null) {
|
||||
$data =& $this->data;
|
||||
}
|
||||
|
||||
$path = is_array($path) ? $path : explode($separator, $path);
|
||||
while (null !== ($part = array_shift($path))) {
|
||||
if (!is_array($data)) {
|
||||
return null;
|
||||
} elseif (isset($data[$part])) {
|
||||
$data =& $data[$part];
|
||||
} elseif ($part != '*') {
|
||||
return null;
|
||||
} else {
|
||||
// Perform a wildcard search by diverging and merging paths
|
||||
$result = array();
|
||||
foreach ($data as $value) {
|
||||
if (!$path) {
|
||||
$result = array_merge_recursive($result, (array) $value);
|
||||
} elseif (null !== ($test = $this->getPath($path, $separator, $value))) {
|
||||
$result = array_merge_recursive($result, (array) $test);
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject configuration settings into an input string
|
||||
*
|
||||
* @param string $input Input to inject
|
||||
*
|
||||
* @return string
|
||||
* @deprecated
|
||||
*/
|
||||
public function inject($input)
|
||||
{
|
||||
Version::warn(__METHOD__ . ' is deprecated');
|
||||
$replace = array();
|
||||
foreach ($this->data as $key => $val) {
|
||||
$replace['{' . $key . '}'] = $val;
|
||||
}
|
||||
|
||||
return strtr($input, $replace);
|
||||
}
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Common;
|
||||
|
||||
use Symfony\Component\EventDispatcher\Event as SymfonyEvent;
|
||||
|
||||
/**
|
||||
* Default event for Guzzle notifications
|
||||
*/
|
||||
class Event extends SymfonyEvent implements ToArrayInterface, \ArrayAccess, \IteratorAggregate
|
||||
{
|
||||
/** @var array */
|
||||
private $context;
|
||||
|
||||
/**
|
||||
* @param array $context Contextual information
|
||||
*/
|
||||
public function __construct(array $context = array())
|
||||
{
|
||||
$this->context = $context;
|
||||
}
|
||||
|
||||
public function getIterator()
|
||||
{
|
||||
return new \ArrayIterator($this->context);
|
||||
}
|
||||
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
return isset($this->context[$offset]) ? $this->context[$offset] : null;
|
||||
}
|
||||
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
$this->context[$offset] = $value;
|
||||
}
|
||||
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
return isset($this->context[$offset]);
|
||||
}
|
||||
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
unset($this->context[$offset]);
|
||||
}
|
||||
|
||||
public function toArray()
|
||||
{
|
||||
return $this->context;
|
||||
}
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Common\Exception;
|
||||
|
||||
class BadMethodCallException extends \BadMethodCallException implements GuzzleException {}
|
|
@ -1,85 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Common\Exception;
|
||||
|
||||
/**
|
||||
* Collection of exceptions
|
||||
*/
|
||||
class ExceptionCollection extends \Exception implements GuzzleException, \IteratorAggregate, \Countable
|
||||
{
|
||||
/** @var array Array of Exceptions */
|
||||
protected $exceptions = array();
|
||||
|
||||
/**
|
||||
* Set all of the exceptions
|
||||
*
|
||||
* @param array $exceptions Array of exceptions
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setExceptions(array $exceptions)
|
||||
{
|
||||
$this->exceptions = array();
|
||||
foreach ($exceptions as $exception) {
|
||||
$this->add($exception);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add exceptions to the collection
|
||||
*
|
||||
* @param ExceptionCollection|\Exception $e Exception to add
|
||||
*
|
||||
* @return ExceptionCollection;
|
||||
*/
|
||||
public function add($e)
|
||||
{
|
||||
if ($this->message) {
|
||||
$this->message .= "\n";
|
||||
}
|
||||
|
||||
if ($e instanceof self) {
|
||||
$this->message .= '(' . get_class($e) . ")";
|
||||
foreach (explode("\n", $e->getMessage()) as $message) {
|
||||
$this->message .= "\n {$message}";
|
||||
}
|
||||
} elseif ($e instanceof \Exception) {
|
||||
$this->exceptions[] = $e;
|
||||
$this->message .= '(' . get_class($e) . ') ' . $e->getMessage();
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the total number of request exceptions
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function count()
|
||||
{
|
||||
return count($this->exceptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows array-like iteration over the request exceptions
|
||||
*
|
||||
* @return \ArrayIterator
|
||||
*/
|
||||
public function getIterator()
|
||||
{
|
||||
return new \ArrayIterator($this->exceptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first exception in the collection
|
||||
*
|
||||
* @return \Exception
|
||||
*/
|
||||
public function getFirst()
|
||||
{
|
||||
return $this->exceptions ? $this->exceptions[0] : null;
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Common\Exception;
|
||||
|
||||
/**
|
||||
* Guzzle exception
|
||||
*/
|
||||
interface GuzzleException {}
|
|
@ -1,5 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Common\Exception;
|
||||
|
||||
class InvalidArgumentException extends \InvalidArgumentException implements GuzzleException {}
|
|
@ -1,5 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Common\Exception;
|
||||
|
||||
class RuntimeException extends \RuntimeException implements GuzzleException {}
|
|
@ -1,5 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Common\Exception;
|
||||
|
||||
class UnexpectedValueException extends \UnexpectedValueException implements GuzzleException {}
|
|
@ -1,18 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Common;
|
||||
|
||||
/**
|
||||
* Interfaces that adds a factory method which is used to instantiate a class from an array of configuration options.
|
||||
*/
|
||||
interface FromConfigInterface
|
||||
{
|
||||
/**
|
||||
* Static factory method used to turn an array or collection of configuration data into an instantiated object.
|
||||
*
|
||||
* @param array|Collection $config Configuration data
|
||||
*
|
||||
* @return FromConfigInterface
|
||||
*/
|
||||
public static function factory($config = array());
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Common;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
/**
|
||||
* Holds an event dispatcher
|
||||
*/
|
||||
interface HasDispatcherInterface
|
||||
{
|
||||
/**
|
||||
* Get a list of all of the events emitted from the class
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getAllEvents();
|
||||
|
||||
/**
|
||||
* Set the EventDispatcher of the request
|
||||
*
|
||||
* @param EventDispatcherInterface $eventDispatcher
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setEventDispatcher(EventDispatcherInterface $eventDispatcher);
|
||||
|
||||
/**
|
||||
* Get the EventDispatcher of the request
|
||||
*
|
||||
* @return EventDispatcherInterface
|
||||
*/
|
||||
public function getEventDispatcher();
|
||||
|
||||
/**
|
||||
* Helper to dispatch Guzzle events and set the event name on the event
|
||||
*
|
||||
* @param string $eventName Name of the event to dispatch
|
||||
* @param array $context Context of the event
|
||||
*/
|
||||
public function dispatch($eventName, array $context = array());
|
||||
|
||||
/**
|
||||
* Add an event subscriber to the dispatcher
|
||||
*
|
||||
* @param EventSubscriberInterface $subscriber Event subscriber
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function addSubscriber(EventSubscriberInterface $subscriber);
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Common;
|
||||
|
||||
/**
|
||||
* Guzzle version information
|
||||
*/
|
||||
class Version
|
||||
{
|
||||
const VERSION = '3.7.1';
|
||||
|
||||
/**
|
||||
* @var bool Set this value to true to enable warnings for deprecated functionality use. This should be on in your
|
||||
* unit tests, but probably not in production.
|
||||
*/
|
||||
public static $emitWarnings = false;
|
||||
|
||||
/**
|
||||
* Emit a deprecation warning
|
||||
*
|
||||
* @param string $message Warning message
|
||||
*/
|
||||
public static function warn($message)
|
||||
{
|
||||
if (self::$emitWarnings) {
|
||||
trigger_error('Deprecation warning: ' . $message, E_USER_DEPRECATED);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
{
|
||||
"name": "guzzle/common",
|
||||
"homepage": "http://guzzlephp.org/",
|
||||
"description": "Common libraries used by Guzzle",
|
||||
"keywords": ["common", "event", "exception", "collection"],
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"php": ">=5.3.2",
|
||||
"symfony/event-dispatcher": ">=2.1"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": { "Guzzle\\Common": "" }
|
||||
},
|
||||
"target-dir": "Guzzle/Common",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.7-dev"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,221 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http;
|
||||
|
||||
use Guzzle\Stream\Stream;
|
||||
|
||||
/**
|
||||
* Abstract decorator used to wrap entity bodies
|
||||
*/
|
||||
class AbstractEntityBodyDecorator implements EntityBodyInterface
|
||||
{
|
||||
/** @var EntityBodyInterface Decorated entity body */
|
||||
protected $body;
|
||||
|
||||
/**
|
||||
* @param EntityBodyInterface $body Entity body to decorate
|
||||
*/
|
||||
public function __construct(EntityBodyInterface $body)
|
||||
{
|
||||
$this->body = $body;
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return (string) $this->body;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow decorators to implement custom methods
|
||||
*
|
||||
* @param string $method Missing method name
|
||||
* @param array $args Method arguments
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call($method, array $args)
|
||||
{
|
||||
return call_user_func_array(array($this->body, $method), $args);
|
||||
}
|
||||
|
||||
public function close()
|
||||
{
|
||||
return $this->body->close();
|
||||
}
|
||||
|
||||
public function setRewindFunction($callable)
|
||||
{
|
||||
$this->body->setRewindFunction($callable);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function rewind()
|
||||
{
|
||||
return $this->body->rewind();
|
||||
}
|
||||
|
||||
public function compress($filter = 'zlib.deflate')
|
||||
{
|
||||
return $this->body->compress($filter);
|
||||
}
|
||||
|
||||
public function uncompress($filter = 'zlib.inflate')
|
||||
{
|
||||
return $this->body->uncompress($filter);
|
||||
}
|
||||
|
||||
public function getContentLength()
|
||||
{
|
||||
return $this->getSize();
|
||||
}
|
||||
|
||||
public function getContentType()
|
||||
{
|
||||
return $this->body->getContentType();
|
||||
}
|
||||
|
||||
public function getContentMd5($rawOutput = false, $base64Encode = false)
|
||||
{
|
||||
$hash = Stream::getHash($this, 'md5', $rawOutput);
|
||||
|
||||
return $hash && $base64Encode ? base64_encode($hash) : $hash;
|
||||
}
|
||||
|
||||
public function getContentEncoding()
|
||||
{
|
||||
return $this->body->getContentEncoding();
|
||||
}
|
||||
|
||||
public function getMetaData($key = null)
|
||||
{
|
||||
return $this->body->getMetaData($key);
|
||||
}
|
||||
|
||||
public function getStream()
|
||||
{
|
||||
return $this->body->getStream();
|
||||
}
|
||||
|
||||
public function setStream($stream, $size = 0)
|
||||
{
|
||||
$this->body->setStream($stream, $size);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function detachStream()
|
||||
{
|
||||
$this->body->detachStream();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getWrapper()
|
||||
{
|
||||
return $this->body->getWrapper();
|
||||
}
|
||||
|
||||
public function getWrapperData()
|
||||
{
|
||||
return $this->body->getWrapperData();
|
||||
}
|
||||
|
||||
public function getStreamType()
|
||||
{
|
||||
return $this->body->getStreamType();
|
||||
}
|
||||
|
||||
public function getUri()
|
||||
{
|
||||
return $this->body->getUri();
|
||||
}
|
||||
|
||||
public function getSize()
|
||||
{
|
||||
return $this->body->getSize();
|
||||
}
|
||||
|
||||
public function isReadable()
|
||||
{
|
||||
return $this->body->isReadable();
|
||||
}
|
||||
|
||||
public function isRepeatable()
|
||||
{
|
||||
return $this->isSeekable() && $this->isReadable();
|
||||
}
|
||||
|
||||
public function isWritable()
|
||||
{
|
||||
return $this->body->isWritable();
|
||||
}
|
||||
|
||||
public function isConsumed()
|
||||
{
|
||||
return $this->body->isConsumed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias of isConsumed()
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function feof()
|
||||
{
|
||||
return $this->isConsumed();
|
||||
}
|
||||
|
||||
public function isLocal()
|
||||
{
|
||||
return $this->body->isLocal();
|
||||
}
|
||||
|
||||
public function isSeekable()
|
||||
{
|
||||
return $this->body->isSeekable();
|
||||
}
|
||||
|
||||
public function setSize($size)
|
||||
{
|
||||
$this->body->setSize($size);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function seek($offset, $whence = SEEK_SET)
|
||||
{
|
||||
return $this->body->seek($offset, $whence);
|
||||
}
|
||||
|
||||
public function read($length)
|
||||
{
|
||||
return $this->body->read($length);
|
||||
}
|
||||
|
||||
public function write($string)
|
||||
{
|
||||
return $this->body->write($string);
|
||||
}
|
||||
|
||||
public function readLine($maxLength = null)
|
||||
{
|
||||
return $this->body->readLine($maxLength);
|
||||
}
|
||||
|
||||
public function ftell()
|
||||
{
|
||||
return $this->body->ftell();
|
||||
}
|
||||
|
||||
public function getCustomData($key)
|
||||
{
|
||||
return $this->body->getCustomData($key);
|
||||
}
|
||||
|
||||
public function setCustomData($key, $value)
|
||||
{
|
||||
$this->body->setCustomData($key, $value);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
|
@ -1,229 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http;
|
||||
|
||||
use Guzzle\Common\Exception\RuntimeException;
|
||||
|
||||
/**
|
||||
* EntityBody decorator that can cache previously read bytes from a sequentially read tstream
|
||||
*/
|
||||
class CachingEntityBody extends AbstractEntityBodyDecorator
|
||||
{
|
||||
/** @var EntityBody Remote stream used to actually pull data onto the buffer */
|
||||
protected $remoteStream;
|
||||
|
||||
/** @var int The number of bytes to skip reading due to a write on the temporary buffer */
|
||||
protected $skipReadBytes = 0;
|
||||
|
||||
/**
|
||||
* We will treat the buffer object as the body of the entity body
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct(EntityBodyInterface $body)
|
||||
{
|
||||
$this->remoteStream = $body;
|
||||
$this->body = new EntityBody(fopen('php://temp', 'r+'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Will give the contents of the buffer followed by the exhausted remote stream.
|
||||
*
|
||||
* Warning: Loads the entire stream into memory
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
$pos = $this->ftell();
|
||||
$this->rewind();
|
||||
|
||||
$str = '';
|
||||
while (!$this->isConsumed()) {
|
||||
$str .= $this->read(16384);
|
||||
}
|
||||
|
||||
$this->seek($pos);
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
public function getSize()
|
||||
{
|
||||
return max($this->body->getSize(), $this->remoteStream->getSize());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @throws RuntimeException When seeking with SEEK_END or when seeking past the total size of the buffer stream
|
||||
*/
|
||||
public function seek($offset, $whence = SEEK_SET)
|
||||
{
|
||||
if ($whence == SEEK_SET) {
|
||||
$byte = $offset;
|
||||
} elseif ($whence == SEEK_CUR) {
|
||||
$byte = $offset + $this->ftell();
|
||||
} else {
|
||||
throw new RuntimeException(__CLASS__ . ' supports only SEEK_SET and SEEK_CUR seek operations');
|
||||
}
|
||||
|
||||
// You cannot skip ahead past where you've read from the remote stream
|
||||
if ($byte > $this->body->getSize()) {
|
||||
throw new RuntimeException(
|
||||
"Cannot seek to byte {$byte} when the buffered stream only contains {$this->body->getSize()} bytes"
|
||||
);
|
||||
}
|
||||
|
||||
return $this->body->seek($byte);
|
||||
}
|
||||
|
||||
public function rewind()
|
||||
{
|
||||
return $this->seek(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Does not support custom rewind functions
|
||||
*
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function setRewindFunction($callable)
|
||||
{
|
||||
throw new RuntimeException(__CLASS__ . ' does not support custom stream rewind functions');
|
||||
}
|
||||
|
||||
public function read($length)
|
||||
{
|
||||
// Perform a regular read on any previously read data from the buffer
|
||||
$data = $this->body->read($length);
|
||||
$remaining = $length - strlen($data);
|
||||
|
||||
// More data was requested so read from the remote stream
|
||||
if ($remaining) {
|
||||
// If data was written to the buffer in a position that would have been filled from the remote stream,
|
||||
// then we must skip bytes on the remote stream to emulate overwriting bytes from that position. This
|
||||
// mimics the behavior of other PHP stream wrappers.
|
||||
$remoteData = $this->remoteStream->read($remaining + $this->skipReadBytes);
|
||||
|
||||
if ($this->skipReadBytes) {
|
||||
$len = strlen($remoteData);
|
||||
$remoteData = substr($remoteData, $this->skipReadBytes);
|
||||
$this->skipReadBytes = max(0, $this->skipReadBytes - $len);
|
||||
}
|
||||
|
||||
$data .= $remoteData;
|
||||
$this->body->write($remoteData);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function write($string)
|
||||
{
|
||||
// When appending to the end of the currently read stream, you'll want to skip bytes from being read from
|
||||
// the remote stream to emulate other stream wrappers. Basically replacing bytes of data of a fixed length.
|
||||
$overflow = (strlen($string) + $this->ftell()) - $this->remoteStream->ftell();
|
||||
if ($overflow > 0) {
|
||||
$this->skipReadBytes += $overflow;
|
||||
}
|
||||
|
||||
return $this->body->write($string);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @link http://php.net/manual/en/function.fgets.php
|
||||
*/
|
||||
public function readLine($maxLength = null)
|
||||
{
|
||||
$buffer = '';
|
||||
$size = 0;
|
||||
while (!$this->isConsumed()) {
|
||||
$byte = $this->read(1);
|
||||
$buffer .= $byte;
|
||||
// Break when a new line is found or the max length - 1 is reached
|
||||
if ($byte == PHP_EOL || ++$size == $maxLength - 1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $buffer;
|
||||
}
|
||||
|
||||
public function isConsumed()
|
||||
{
|
||||
return $this->body->isConsumed() && $this->remoteStream->isConsumed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Close both the remote stream and buffer stream
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
return $this->remoteStream->close() && $this->body->close();
|
||||
}
|
||||
|
||||
public function setStream($stream, $size = 0)
|
||||
{
|
||||
$this->remoteStream->setStream($stream, $size);
|
||||
}
|
||||
|
||||
public function getContentType()
|
||||
{
|
||||
return $this->remoteStream->getContentType();
|
||||
}
|
||||
|
||||
public function getContentEncoding()
|
||||
{
|
||||
return $this->remoteStream->getContentEncoding();
|
||||
}
|
||||
|
||||
public function getMetaData($key = null)
|
||||
{
|
||||
return $this->remoteStream->getMetaData($key);
|
||||
}
|
||||
|
||||
public function getStream()
|
||||
{
|
||||
return $this->remoteStream->getStream();
|
||||
}
|
||||
|
||||
public function getWrapper()
|
||||
{
|
||||
return $this->remoteStream->getWrapper();
|
||||
}
|
||||
|
||||
public function getWrapperData()
|
||||
{
|
||||
return $this->remoteStream->getWrapperData();
|
||||
}
|
||||
|
||||
public function getStreamType()
|
||||
{
|
||||
return $this->remoteStream->getStreamType();
|
||||
}
|
||||
|
||||
public function getUri()
|
||||
{
|
||||
return $this->remoteStream->getUri();
|
||||
}
|
||||
|
||||
/**
|
||||
* Always retrieve custom data from the remote stream
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCustomData($key)
|
||||
{
|
||||
return $this->remoteStream->getCustomData($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Always set custom data on the remote stream
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setCustomData($key, $value)
|
||||
{
|
||||
$this->remoteStream->setCustomData($key, $value);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
|
@ -1,506 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http;
|
||||
|
||||
use Guzzle\Common\Collection;
|
||||
use Guzzle\Common\AbstractHasDispatcher;
|
||||
use Guzzle\Common\Exception\ExceptionCollection;
|
||||
use Guzzle\Common\Exception\InvalidArgumentException;
|
||||
use Guzzle\Common\Exception\RuntimeException;
|
||||
use Guzzle\Common\Version;
|
||||
use Guzzle\Parser\ParserRegistry;
|
||||
use Guzzle\Parser\UriTemplate\UriTemplateInterface;
|
||||
use Guzzle\Http\Message\RequestInterface;
|
||||
use Guzzle\Http\Message\RequestFactory;
|
||||
use Guzzle\Http\Message\RequestFactoryInterface;
|
||||
use Guzzle\Http\Curl\CurlMultiInterface;
|
||||
use Guzzle\Http\Curl\CurlMultiProxy;
|
||||
use Guzzle\Http\Curl\CurlHandle;
|
||||
use Guzzle\Http\Curl\CurlVersion;
|
||||
|
||||
/**
|
||||
* HTTP client
|
||||
*/
|
||||
class Client extends AbstractHasDispatcher implements ClientInterface
|
||||
{
|
||||
/** @deprecated Use [request.options][params] */
|
||||
const REQUEST_PARAMS = 'request.params';
|
||||
|
||||
const REQUEST_OPTIONS = 'request.options';
|
||||
const CURL_OPTIONS = 'curl.options';
|
||||
const SSL_CERT_AUTHORITY = 'ssl.certificate_authority';
|
||||
const DISABLE_REDIRECTS = RedirectPlugin::DISABLE;
|
||||
|
||||
/** @var Collection Default HTTP headers to set on each request */
|
||||
protected $defaultHeaders;
|
||||
|
||||
/** @var string The user agent string to set on each request */
|
||||
protected $userAgent;
|
||||
|
||||
/** @var Collection Parameter object holding configuration data */
|
||||
private $config;
|
||||
|
||||
/** @var Url Base URL of the client */
|
||||
private $baseUrl;
|
||||
|
||||
/** @var CurlMultiInterface CurlMulti object used internally */
|
||||
private $curlMulti;
|
||||
|
||||
/** @var UriTemplateInterface URI template owned by the client */
|
||||
private $uriTemplate;
|
||||
|
||||
/** @var RequestFactoryInterface Request factory used by the client */
|
||||
protected $requestFactory;
|
||||
|
||||
public static function getAllEvents()
|
||||
{
|
||||
return array(self::CREATE_REQUEST);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $baseUrl Base URL of the web service
|
||||
* @param array|Collection $config Configuration settings
|
||||
*
|
||||
* @throws RuntimeException if cURL is not installed
|
||||
*/
|
||||
public function __construct($baseUrl = '', $config = null)
|
||||
{
|
||||
if (!extension_loaded('curl')) {
|
||||
// @codeCoverageIgnoreStart
|
||||
throw new RuntimeException('The PHP cURL extension must be installed to use Guzzle.');
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
$this->setConfig($config ?: new Collection());
|
||||
$this->initSsl();
|
||||
$this->setBaseUrl($baseUrl);
|
||||
$this->defaultHeaders = new Collection();
|
||||
$this->setRequestFactory(RequestFactory::getInstance());
|
||||
$this->userAgent = $this->getDefaultUserAgent();
|
||||
if (!$this->config[self::DISABLE_REDIRECTS]) {
|
||||
$this->addSubscriber(new RedirectPlugin());
|
||||
}
|
||||
}
|
||||
|
||||
final public function setConfig($config)
|
||||
{
|
||||
if ($config instanceof Collection) {
|
||||
$this->config = $config;
|
||||
} elseif (is_array($config)) {
|
||||
$this->config = new Collection($config);
|
||||
} else {
|
||||
throw new InvalidArgumentException('Config must be an array or Collection');
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
final public function getConfig($key = false)
|
||||
{
|
||||
return $key ? $this->config[$key] : $this->config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a default request option on the client that will be used as a default for each request
|
||||
*
|
||||
* @param string $keyOrPath request.options key (e.g. allow_redirects) or path to a nested key (e.g. headers/foo)
|
||||
* @param mixed $value Value to set
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setDefaultOption($keyOrPath, $value)
|
||||
{
|
||||
$keyOrPath = self::REQUEST_OPTIONS . '/' . $keyOrPath;
|
||||
$this->config->setPath($keyOrPath, $value);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a default request option from the client
|
||||
*
|
||||
* @param string $keyOrPath request.options key (e.g. allow_redirects) or path to a nested key (e.g. headers/foo)
|
||||
*
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function getDefaultOption($keyOrPath)
|
||||
{
|
||||
$keyOrPath = self::REQUEST_OPTIONS . '/' . $keyOrPath;
|
||||
|
||||
return $this->config->getPath($keyOrPath);
|
||||
}
|
||||
|
||||
final public function setSslVerification($certificateAuthority = true, $verifyPeer = true, $verifyHost = 2)
|
||||
{
|
||||
$opts = $this->config[self::CURL_OPTIONS] ?: array();
|
||||
|
||||
if ($certificateAuthority === true) {
|
||||
// use bundled CA bundle, set secure defaults
|
||||
$opts[CURLOPT_CAINFO] = __DIR__ . '/Resources/cacert.pem';
|
||||
$opts[CURLOPT_SSL_VERIFYPEER] = true;
|
||||
$opts[CURLOPT_SSL_VERIFYHOST] = 2;
|
||||
} elseif ($certificateAuthority === false) {
|
||||
unset($opts[CURLOPT_CAINFO]);
|
||||
$opts[CURLOPT_SSL_VERIFYPEER] = false;
|
||||
$opts[CURLOPT_SSL_VERIFYHOST] = 2;
|
||||
} elseif ($verifyPeer !== true && $verifyPeer !== false && $verifyPeer !== 1 && $verifyPeer !== 0) {
|
||||
throw new InvalidArgumentException('verifyPeer must be 1, 0 or boolean');
|
||||
} elseif ($verifyHost !== 0 && $verifyHost !== 1 && $verifyHost !== 2) {
|
||||
throw new InvalidArgumentException('verifyHost must be 0, 1 or 2');
|
||||
} else {
|
||||
$opts[CURLOPT_SSL_VERIFYPEER] = $verifyPeer;
|
||||
$opts[CURLOPT_SSL_VERIFYHOST] = $verifyHost;
|
||||
if (is_file($certificateAuthority)) {
|
||||
unset($opts[CURLOPT_CAPATH]);
|
||||
$opts[CURLOPT_CAINFO] = $certificateAuthority;
|
||||
} elseif (is_dir($certificateAuthority)) {
|
||||
unset($opts[CURLOPT_CAINFO]);
|
||||
$opts[CURLOPT_CAPATH] = $certificateAuthority;
|
||||
} else {
|
||||
throw new RuntimeException(
|
||||
'Invalid option passed to ' . self::SSL_CERT_AUTHORITY . ': ' . $certificateAuthority
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$this->config->set(self::CURL_OPTIONS, $opts);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function createRequest($method = 'GET', $uri = null, $headers = null, $body = null, array $options = array())
|
||||
{
|
||||
if (!$uri) {
|
||||
$url = $this->getBaseUrl();
|
||||
} else {
|
||||
if (!is_array($uri)) {
|
||||
$templateVars = null;
|
||||
} else {
|
||||
list($uri, $templateVars) = $uri;
|
||||
}
|
||||
if (substr($uri, 0, 4) === 'http') {
|
||||
// Use absolute URLs as-is
|
||||
$url = $this->expandTemplate($uri, $templateVars);
|
||||
} else {
|
||||
$url = Url::factory($this->getBaseUrl())->combine($this->expandTemplate($uri, $templateVars));
|
||||
}
|
||||
}
|
||||
|
||||
// If default headers are provided, then merge them under any explicitly provided headers for the request
|
||||
if (count($this->defaultHeaders)) {
|
||||
if (!$headers) {
|
||||
$headers = $this->defaultHeaders->toArray();
|
||||
} elseif (is_array($headers)) {
|
||||
$headers += $this->defaultHeaders->toArray();
|
||||
} elseif ($headers instanceof Collection) {
|
||||
$headers = $headers->toArray() + $this->defaultHeaders->toArray();
|
||||
}
|
||||
}
|
||||
|
||||
return $this->prepareRequest($this->requestFactory->create($method, (string) $url, $headers, $body), $options);
|
||||
}
|
||||
|
||||
public function getBaseUrl($expand = true)
|
||||
{
|
||||
return $expand ? $this->expandTemplate($this->baseUrl) : $this->baseUrl;
|
||||
}
|
||||
|
||||
public function setBaseUrl($url)
|
||||
{
|
||||
$this->baseUrl = $url;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setUserAgent($userAgent, $includeDefault = false)
|
||||
{
|
||||
if ($includeDefault) {
|
||||
$userAgent .= ' ' . $this->getDefaultUserAgent();
|
||||
}
|
||||
$this->userAgent = $userAgent;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default User-Agent string to use with Guzzle
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDefaultUserAgent()
|
||||
{
|
||||
return 'Guzzle/' . Version::VERSION
|
||||
. ' curl/' . CurlVersion::getInstance()->get('version')
|
||||
. ' PHP/' . PHP_VERSION;
|
||||
}
|
||||
|
||||
public function get($uri = null, $headers = null, $options = array())
|
||||
{
|
||||
// BC compat: $options can be a string, resource, etc to specify where the response body is downloaded
|
||||
return is_array($options)
|
||||
? $this->createRequest('GET', $uri, $headers, null, $options)
|
||||
: $this->createRequest('GET', $uri, $headers, $options);
|
||||
}
|
||||
|
||||
public function head($uri = null, $headers = null, array $options = array())
|
||||
{
|
||||
return $this->createRequest('HEAD', $uri, $headers, null, $options);
|
||||
}
|
||||
|
||||
public function delete($uri = null, $headers = null, $body = null, array $options = array())
|
||||
{
|
||||
return $this->createRequest('DELETE', $uri, $headers, $body, $options);
|
||||
}
|
||||
|
||||
public function put($uri = null, $headers = null, $body = null, array $options = array())
|
||||
{
|
||||
return $this->createRequest('PUT', $uri, $headers, $body, $options);
|
||||
}
|
||||
|
||||
public function patch($uri = null, $headers = null, $body = null, array $options = array())
|
||||
{
|
||||
return $this->createRequest('PATCH', $uri, $headers, $body, $options);
|
||||
}
|
||||
|
||||
public function post($uri = null, $headers = null, $postBody = null, array $options = array())
|
||||
{
|
||||
return $this->createRequest('POST', $uri, $headers, $postBody, $options);
|
||||
}
|
||||
|
||||
public function options($uri = null, array $options = array())
|
||||
{
|
||||
return $this->createRequest('OPTIONS', $uri, $options);
|
||||
}
|
||||
|
||||
public function send($requests)
|
||||
{
|
||||
if (!($requests instanceof RequestInterface)) {
|
||||
return $this->sendMultiple($requests);
|
||||
}
|
||||
|
||||
try {
|
||||
/** @var $requests RequestInterface */
|
||||
$this->getCurlMulti()->add($requests)->send();
|
||||
return $requests->getResponse();
|
||||
} catch (ExceptionCollection $e) {
|
||||
throw $e->getFirst();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a curl multi object to be used internally by the client for transferring requests.
|
||||
*
|
||||
* @param CurlMultiInterface $curlMulti Multi object
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setCurlMulti(CurlMultiInterface $curlMulti)
|
||||
{
|
||||
$this->curlMulti = $curlMulti;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return CurlMultiInterface|CurlMultiProxy
|
||||
*/
|
||||
public function getCurlMulti()
|
||||
{
|
||||
if (!$this->curlMulti) {
|
||||
$this->curlMulti = new CurlMultiProxy();
|
||||
}
|
||||
|
||||
return $this->curlMulti;
|
||||
}
|
||||
|
||||
public function setRequestFactory(RequestFactoryInterface $factory)
|
||||
{
|
||||
$this->requestFactory = $factory;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the URI template expander to use with the client
|
||||
*
|
||||
* @param UriTemplateInterface $uriTemplate URI template expander
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setUriTemplate(UriTemplateInterface $uriTemplate)
|
||||
{
|
||||
$this->uriTemplate = $uriTemplate;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the cacert.pem file from the phar if it is not in the temp folder and validate the MD5 checksum
|
||||
*
|
||||
* @param bool $md5Check Set to false to not perform the MD5 validation
|
||||
*
|
||||
* @return string Returns the path to the extracted cacert
|
||||
* @throws RuntimeException if the file cannot be copied or there is a MD5 mismatch
|
||||
*/
|
||||
public function preparePharCacert($md5Check = true)
|
||||
{
|
||||
$from = __DIR__ . '/Resources/cacert.pem';
|
||||
$certFile = sys_get_temp_dir() . '/guzzle-cacert.pem';
|
||||
if (!file_exists($certFile) && !copy($from, $certFile)) {
|
||||
throw new RuntimeException("Could not copy {$from} to {$certFile}: " . var_export(error_get_last(), true));
|
||||
} elseif ($md5Check) {
|
||||
$actualMd5 = md5_file($certFile);
|
||||
$expectedMd5 = trim(file_get_contents("{$from}.md5"));
|
||||
if ($actualMd5 != $expectedMd5) {
|
||||
throw new RuntimeException("{$certFile} MD5 mismatch: expected {$expectedMd5} but got {$actualMd5}");
|
||||
}
|
||||
}
|
||||
|
||||
return $certFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expand a URI template while merging client config settings into the template variables
|
||||
*
|
||||
* @param string $template Template to expand
|
||||
* @param array $variables Variables to inject
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function expandTemplate($template, array $variables = null)
|
||||
{
|
||||
$expansionVars = $this->getConfig()->toArray();
|
||||
if ($variables) {
|
||||
$expansionVars = $variables + $expansionVars;
|
||||
}
|
||||
|
||||
return $this->getUriTemplate()->expand($template, $expansionVars);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the URI template expander used by the client
|
||||
*
|
||||
* @return UriTemplateInterface
|
||||
*/
|
||||
protected function getUriTemplate()
|
||||
{
|
||||
if (!$this->uriTemplate) {
|
||||
$this->uriTemplate = ParserRegistry::getInstance()->getParser('uri_template');
|
||||
}
|
||||
|
||||
return $this->uriTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send multiple requests in parallel
|
||||
*
|
||||
* @param array $requests Array of RequestInterface objects
|
||||
*
|
||||
* @return array Returns an array of Response objects
|
||||
*/
|
||||
protected function sendMultiple(array $requests)
|
||||
{
|
||||
$curlMulti = $this->getCurlMulti();
|
||||
foreach ($requests as $request) {
|
||||
$curlMulti->add($request);
|
||||
}
|
||||
$curlMulti->send();
|
||||
|
||||
/** @var $request RequestInterface */
|
||||
$result = array();
|
||||
foreach ($requests as $request) {
|
||||
$result[] = $request->getResponse();
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare a request to be sent from the Client by adding client specific behaviors and properties to the request.
|
||||
*
|
||||
* @param RequestInterface $request Request to prepare for the client
|
||||
* @param array $options Options to apply to the request
|
||||
*
|
||||
* @return RequestInterface
|
||||
*/
|
||||
protected function prepareRequest(RequestInterface $request, array $options = array())
|
||||
{
|
||||
$request->setClient($this)->setEventDispatcher(clone $this->getEventDispatcher());
|
||||
|
||||
if ($curl = $this->config[self::CURL_OPTIONS]) {
|
||||
$request->getCurlOptions()->overwriteWith(CurlHandle::parseCurlConfig($curl));
|
||||
}
|
||||
|
||||
if ($params = $this->config[self::REQUEST_PARAMS]) {
|
||||
Version::warn('request.params is deprecated. Use request.options to add default request options.');
|
||||
$request->getParams()->overwriteWith($params);
|
||||
}
|
||||
|
||||
if ($this->userAgent && !$request->hasHeader('User-Agent')) {
|
||||
$request->setHeader('User-Agent', $this->userAgent);
|
||||
}
|
||||
|
||||
if ($defaults = $this->config[self::REQUEST_OPTIONS]) {
|
||||
$this->requestFactory->applyOptions($request, $defaults, RequestFactoryInterface::OPTIONS_AS_DEFAULTS);
|
||||
}
|
||||
|
||||
if ($options) {
|
||||
$this->requestFactory->applyOptions($request, $options);
|
||||
}
|
||||
|
||||
$this->dispatch('client.create_request', array('client' => $this, 'request' => $request));
|
||||
|
||||
return $request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes SSL settings
|
||||
*/
|
||||
protected function initSsl()
|
||||
{
|
||||
if ('system' == ($authority = $this->config[self::SSL_CERT_AUTHORITY])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($authority === null) {
|
||||
$authority = true;
|
||||
}
|
||||
|
||||
if ($authority === true && substr(__FILE__, 0, 7) == 'phar://') {
|
||||
$authority = $this->preparePharCacert();
|
||||
$that = $this;
|
||||
$this->getEventDispatcher()->addListener('request.before_send', function ($event) use ($authority, $that) {
|
||||
if ($authority == $event['request']->getCurlOptions()->get(CURLOPT_CAINFO)) {
|
||||
$that->preparePharCacert(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$this->setSslVerification($authority);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
public function getDefaultHeaders()
|
||||
{
|
||||
Version::warn(__METHOD__ . ' is deprecated. Use the request.options array to retrieve default request options');
|
||||
return $this->defaultHeaders;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
public function setDefaultHeaders($headers)
|
||||
{
|
||||
Version::warn(__METHOD__ . ' is deprecated. Use the request.options array to specify default request options');
|
||||
if ($headers instanceof Collection) {
|
||||
$this->defaultHeaders = $headers;
|
||||
} elseif (is_array($headers)) {
|
||||
$this->defaultHeaders = new Collection($headers);
|
||||
} else {
|
||||
throw new InvalidArgumentException('Headers must be an array or Collection');
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
|
@ -1,223 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http;
|
||||
|
||||
use Guzzle\Common\HasDispatcherInterface;
|
||||
use Guzzle\Common\Collection;
|
||||
use Guzzle\Common\Exception\InvalidArgumentException;
|
||||
use Guzzle\Http\Message\EntityEnclosingRequestInterface;
|
||||
use Guzzle\Http\Message\RequestInterface;
|
||||
|
||||
/**
|
||||
* Client interface for send HTTP requests
|
||||
*/
|
||||
interface ClientInterface extends HasDispatcherInterface
|
||||
{
|
||||
const CREATE_REQUEST = 'client.create_request';
|
||||
|
||||
/** @var string RFC 1123 HTTP-Date */
|
||||
const HTTP_DATE = 'D, d M Y H:i:s \G\M\T';
|
||||
|
||||
/**
|
||||
* Set the configuration object to use with the client
|
||||
*
|
||||
* @param array|Collection $config Parameters that define how the client behaves
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setConfig($config);
|
||||
|
||||
/**
|
||||
* Get a configuration setting or all of the configuration settings. The Collection result of this method can be
|
||||
* modified to change the configuration settings of a client.
|
||||
*
|
||||
* A client should honor the following special values:
|
||||
*
|
||||
* - request.options: Associative array of default RequestFactory options to apply to each request
|
||||
* - request.params: Associative array of request parameters (data values) to apply to each request
|
||||
* - curl.options: Associative array of cURL configuration settings to apply to each request
|
||||
* - ssl.certificate_authority: Path a CAINFO, CAPATH, true to use strict defaults, or false to disable verification
|
||||
* - redirect.disable: Set to true to disable redirects
|
||||
*
|
||||
* @param bool|string $key Configuration value to retrieve. Set to FALSE to retrieve all values of the client.
|
||||
* The object return can be modified, and modifications will affect the client's config.
|
||||
* @return mixed|Collection
|
||||
* @see \Guzzle\Http\Message\RequestFactoryInterface::applyOptions for a full list of request.options options
|
||||
*/
|
||||
public function getConfig($key = false);
|
||||
|
||||
/**
|
||||
* Create and return a new {@see RequestInterface} configured for the client.
|
||||
*
|
||||
* Use an absolute path to override the base path of the client, or a relative path to append to the base path of
|
||||
* the client. The URI can contain the query string as well. Use an array to provide a URI template and additional
|
||||
* variables to use in the URI template expansion.
|
||||
*
|
||||
* @param string $method HTTP method. Defaults to GET
|
||||
* @param string|array $uri Resource URI.
|
||||
* @param array|Collection $headers HTTP headers
|
||||
* @param string|resource|array|EntityBodyInterface $body Entity body of request (POST/PUT) or response (GET)
|
||||
* @param array $options Array of options to apply to the request
|
||||
*
|
||||
* @return RequestInterface
|
||||
* @throws InvalidArgumentException if a URI array is passed that does not contain exactly two elements: the URI
|
||||
* followed by template variables
|
||||
*/
|
||||
public function createRequest(
|
||||
$method = RequestInterface::GET,
|
||||
$uri = null,
|
||||
$headers = null,
|
||||
$body = null,
|
||||
array $options = array()
|
||||
);
|
||||
|
||||
/**
|
||||
* Create a GET request for the client
|
||||
*
|
||||
* @param string|array $uri Resource URI
|
||||
* @param array|Collection $headers HTTP headers
|
||||
* @param array $options Options to apply to the request. For BC compatibility, you can also pass a
|
||||
* string to tell Guzzle to download the body of the response to a particular
|
||||
* location. Use the 'body' option instead for forward compatibility.
|
||||
* @return RequestInterface
|
||||
* @see Guzzle\Http\ClientInterface::createRequest()
|
||||
*/
|
||||
public function get($uri = null, $headers = null, $options = array());
|
||||
|
||||
/**
|
||||
* Create a HEAD request for the client
|
||||
*
|
||||
* @param string|array $uri Resource URI
|
||||
* @param array|Collection $headers HTTP headers
|
||||
* @param array $options Options to apply to the request
|
||||
*
|
||||
* @return RequestInterface
|
||||
* @see Guzzle\Http\ClientInterface::createRequest()
|
||||
*/
|
||||
public function head($uri = null, $headers = null, array $options = array());
|
||||
|
||||
/**
|
||||
* Create a DELETE request for the client
|
||||
*
|
||||
* @param string|array $uri Resource URI
|
||||
* @param array|Collection $headers HTTP headers
|
||||
* @param string|resource|EntityBodyInterface $body Body to send in the request
|
||||
* @param array $options Options to apply to the request
|
||||
*
|
||||
* @return EntityEnclosingRequestInterface
|
||||
* @see Guzzle\Http\ClientInterface::createRequest()
|
||||
*/
|
||||
public function delete($uri = null, $headers = null, $body = null, array $options = array());
|
||||
|
||||
/**
|
||||
* Create a PUT request for the client
|
||||
*
|
||||
* @param string|array $uri Resource URI
|
||||
* @param array|Collection $headers HTTP headers
|
||||
* @param string|resource|EntityBodyInterface $body Body to send in the request
|
||||
* @param array $options Options to apply to the request
|
||||
*
|
||||
* @return EntityEnclosingRequestInterface
|
||||
* @see Guzzle\Http\ClientInterface::createRequest()
|
||||
*/
|
||||
public function put($uri = null, $headers = null, $body = null, array $options = array());
|
||||
|
||||
/**
|
||||
* Create a PATCH request for the client
|
||||
*
|
||||
* @param string|array $uri Resource URI
|
||||
* @param array|Collection $headers HTTP headers
|
||||
* @param string|resource|EntityBodyInterface $body Body to send in the request
|
||||
* @param array $options Options to apply to the request
|
||||
*
|
||||
* @return EntityEnclosingRequestInterface
|
||||
* @see Guzzle\Http\ClientInterface::createRequest()
|
||||
*/
|
||||
public function patch($uri = null, $headers = null, $body = null, array $options = array());
|
||||
|
||||
/**
|
||||
* Create a POST request for the client
|
||||
*
|
||||
* @param string|array $uri Resource URI
|
||||
* @param array|Collection $headers HTTP headers
|
||||
* @param array|Collection|string|EntityBodyInterface $postBody POST body. Can be a string, EntityBody, or
|
||||
* associative array of POST fields to send in the body of the
|
||||
* request. Prefix a value in the array with the @ symbol to
|
||||
* reference a file.
|
||||
* @param array $options Options to apply to the request
|
||||
*
|
||||
* @return EntityEnclosingRequestInterface
|
||||
* @see Guzzle\Http\ClientInterface::createRequest()
|
||||
*/
|
||||
public function post($uri = null, $headers = null, $postBody = null, array $options = array());
|
||||
|
||||
/**
|
||||
* Create an OPTIONS request for the client
|
||||
*
|
||||
* @param string|array $uri Resource URI
|
||||
* @param array $options Options to apply to the request
|
||||
*
|
||||
* @return RequestInterface
|
||||
* @see Guzzle\Http\ClientInterface::createRequest()
|
||||
*/
|
||||
public function options($uri = null, array $options = array());
|
||||
|
||||
/**
|
||||
* Sends a single request or an array of requests in parallel
|
||||
*
|
||||
* @param array|RequestInterface $requests One or more RequestInterface objects to send
|
||||
*
|
||||
* @return \Guzzle\Http\Message\Response|array Returns a single Response or an array of Response objects
|
||||
*/
|
||||
public function send($requests);
|
||||
|
||||
/**
|
||||
* Get the client's base URL as either an expanded or raw URI template
|
||||
*
|
||||
* @param bool $expand Set to FALSE to get the raw base URL without URI template expansion
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getBaseUrl($expand = true);
|
||||
|
||||
/**
|
||||
* Set the base URL of the client
|
||||
*
|
||||
* @param string $url The base service endpoint URL of the webservice
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setBaseUrl($url);
|
||||
|
||||
/**
|
||||
* Set the User-Agent header to be used on all requests from the client
|
||||
*
|
||||
* @param string $userAgent User agent string
|
||||
* @param bool $includeDefault Set to true to prepend the value to Guzzle's default user agent string
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setUserAgent($userAgent, $includeDefault = false);
|
||||
|
||||
/**
|
||||
* Set SSL verification options.
|
||||
*
|
||||
* Setting $certificateAuthority to TRUE will result in the bundled cacert.pem being used to verify against the
|
||||
* remote host.
|
||||
*
|
||||
* Alternate certificates to verify against can be specified with the $certificateAuthority option set to the full
|
||||
* path to a certificate file, or the path to a directory containing certificates.
|
||||
*
|
||||
* Setting $certificateAuthority to FALSE will turn off peer verification, unset the bundled cacert.pem, and
|
||||
* disable host verification. Please don't do this unless you really know what you're doing, and why you're doing
|
||||
* it.
|
||||
*
|
||||
* @param string|bool $certificateAuthority bool, file path, or directory path
|
||||
* @param bool $verifyPeer FALSE to stop from verifying the peer's certificate.
|
||||
* @param int $verifyHost Set to 1 to check the existence of a common name in the SSL peer
|
||||
* certificate. 2 to check the existence of a common name and also verify
|
||||
* that it matches the hostname provided.
|
||||
* @return self
|
||||
*/
|
||||
public function setSslVerification($certificateAuthority = true, $verifyPeer = true, $verifyHost = 2);
|
||||
}
|
|
@ -1,451 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http\Curl;
|
||||
|
||||
use Guzzle\Common\Exception\InvalidArgumentException;
|
||||
use Guzzle\Common\Exception\RuntimeException;
|
||||
use Guzzle\Common\Collection;
|
||||
use Guzzle\Http\Message\EntityEnclosingRequest;
|
||||
use Guzzle\Http\Message\RequestInterface;
|
||||
use Guzzle\Parser\ParserRegistry;
|
||||
use Guzzle\Http\Url;
|
||||
|
||||
/**
|
||||
* Immutable wrapper for a cURL handle
|
||||
*/
|
||||
class CurlHandle
|
||||
{
|
||||
const BODY_AS_STRING = 'body_as_string';
|
||||
const PROGRESS = 'progress';
|
||||
const DEBUG = 'debug';
|
||||
|
||||
/** @var Collection Curl options */
|
||||
protected $options;
|
||||
|
||||
/** @var resource Curl resource handle */
|
||||
protected $handle;
|
||||
|
||||
/** @var int CURLE_* error */
|
||||
protected $errorNo = CURLE_OK;
|
||||
|
||||
/**
|
||||
* Factory method to create a new curl handle based on an HTTP request.
|
||||
*
|
||||
* There are some helpful options you can set to enable specific behavior:
|
||||
* - debug: Set to true to enable cURL debug functionality to track the actual headers sent over the wire.
|
||||
* - progress: Set to true to enable progress function callbacks.
|
||||
*
|
||||
* @param RequestInterface $request Request
|
||||
*
|
||||
* @return CurlHandle
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public static function factory(RequestInterface $request)
|
||||
{
|
||||
$requestCurlOptions = $request->getCurlOptions();
|
||||
$mediator = new RequestMediator($request, $requestCurlOptions->get('emit_io'));
|
||||
$tempContentLength = null;
|
||||
$method = $request->getMethod();
|
||||
$bodyAsString = $requestCurlOptions->get(self::BODY_AS_STRING);
|
||||
|
||||
// Array of default cURL options.
|
||||
$curlOptions = array(
|
||||
CURLOPT_URL => $request->getUrl(),
|
||||
CURLOPT_CONNECTTIMEOUT => 150,
|
||||
CURLOPT_RETURNTRANSFER => false,
|
||||
CURLOPT_HEADER => false,
|
||||
CURLOPT_PORT => $request->getPort(),
|
||||
CURLOPT_HTTPHEADER => array(),
|
||||
CURLOPT_WRITEFUNCTION => array($mediator, 'writeResponseBody'),
|
||||
CURLOPT_HEADERFUNCTION => array($mediator, 'receiveResponseHeader'),
|
||||
CURLOPT_HTTP_VERSION => $request->getProtocolVersion() === '1.0'
|
||||
? CURL_HTTP_VERSION_1_0 : CURL_HTTP_VERSION_1_1,
|
||||
// Verifies the authenticity of the peer's certificate
|
||||
CURLOPT_SSL_VERIFYPEER => 1,
|
||||
// Certificate must indicate that the server is the server to which you meant to connect
|
||||
CURLOPT_SSL_VERIFYHOST => 2
|
||||
);
|
||||
|
||||
if (defined('CURLOPT_PROTOCOLS')) {
|
||||
// Allow only HTTP and HTTPS protocols
|
||||
$curlOptions[CURLOPT_PROTOCOLS] = CURLPROTO_HTTP | CURLPROTO_HTTPS;
|
||||
}
|
||||
|
||||
// Add CURLOPT_ENCODING if Accept-Encoding header is provided
|
||||
if ($acceptEncodingHeader = $request->getHeader('Accept-Encoding')) {
|
||||
$curlOptions[CURLOPT_ENCODING] = (string) $acceptEncodingHeader;
|
||||
// Let cURL set the Accept-Encoding header, prevents duplicate values
|
||||
$request->removeHeader('Accept-Encoding');
|
||||
}
|
||||
|
||||
// Enable curl debug information if the 'debug' param was set
|
||||
if ($requestCurlOptions->get('debug')) {
|
||||
$curlOptions[CURLOPT_STDERR] = fopen('php://temp', 'r+');
|
||||
// @codeCoverageIgnoreStart
|
||||
if (false === $curlOptions[CURLOPT_STDERR]) {
|
||||
throw new RuntimeException('Unable to create a stream for CURLOPT_STDERR');
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
$curlOptions[CURLOPT_VERBOSE] = true;
|
||||
}
|
||||
|
||||
// Specify settings according to the HTTP method
|
||||
if ($method == 'GET') {
|
||||
$curlOptions[CURLOPT_HTTPGET] = true;
|
||||
} elseif ($method == 'HEAD') {
|
||||
$curlOptions[CURLOPT_NOBODY] = true;
|
||||
// HEAD requests do not use a write function
|
||||
unset($curlOptions[CURLOPT_WRITEFUNCTION]);
|
||||
} elseif (!($request instanceof EntityEnclosingRequest)) {
|
||||
$curlOptions[CURLOPT_CUSTOMREQUEST] = $method;
|
||||
} else {
|
||||
|
||||
$curlOptions[CURLOPT_CUSTOMREQUEST] = $method;
|
||||
|
||||
// Handle sending raw bodies in a request
|
||||
if ($request->getBody()) {
|
||||
// You can send the body as a string using curl's CURLOPT_POSTFIELDS
|
||||
if ($bodyAsString) {
|
||||
$curlOptions[CURLOPT_POSTFIELDS] = (string) $request->getBody();
|
||||
// Allow curl to add the Content-Length for us to account for the times when
|
||||
// POST redirects are followed by GET requests
|
||||
if ($tempContentLength = $request->getHeader('Content-Length')) {
|
||||
$tempContentLength = (int) (string) $tempContentLength;
|
||||
}
|
||||
// Remove the curl generated Content-Type header if none was set manually
|
||||
if (!$request->hasHeader('Content-Type')) {
|
||||
$curlOptions[CURLOPT_HTTPHEADER][] = 'Content-Type:';
|
||||
}
|
||||
} else {
|
||||
$curlOptions[CURLOPT_UPLOAD] = true;
|
||||
// Let cURL handle setting the Content-Length header
|
||||
if ($tempContentLength = $request->getHeader('Content-Length')) {
|
||||
$tempContentLength = (int) (string) $tempContentLength;
|
||||
$curlOptions[CURLOPT_INFILESIZE] = $tempContentLength;
|
||||
}
|
||||
// Add a callback for curl to read data to send with the request only if a body was specified
|
||||
$curlOptions[CURLOPT_READFUNCTION] = array($mediator, 'readRequestBody');
|
||||
// Attempt to seek to the start of the stream
|
||||
$request->getBody()->seek(0);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// Special handling for POST specific fields and files
|
||||
$postFields = false;
|
||||
if (count($request->getPostFiles())) {
|
||||
$postFields = $request->getPostFields()->useUrlEncoding(false)->urlEncode();
|
||||
foreach ($request->getPostFiles() as $key => $data) {
|
||||
$prefixKeys = count($data) > 1;
|
||||
foreach ($data as $index => $file) {
|
||||
// Allow multiple files in the same key
|
||||
$fieldKey = $prefixKeys ? "{$key}[{$index}]" : $key;
|
||||
$postFields[$fieldKey] = $file->getCurlValue();
|
||||
}
|
||||
}
|
||||
} elseif (count($request->getPostFields())) {
|
||||
$postFields = (string) $request->getPostFields()->useUrlEncoding(true);
|
||||
}
|
||||
|
||||
if ($postFields !== false) {
|
||||
if ($method == 'POST') {
|
||||
unset($curlOptions[CURLOPT_CUSTOMREQUEST]);
|
||||
$curlOptions[CURLOPT_POST] = true;
|
||||
}
|
||||
$curlOptions[CURLOPT_POSTFIELDS] = $postFields;
|
||||
$request->removeHeader('Content-Length');
|
||||
}
|
||||
}
|
||||
|
||||
// If the Expect header is not present, prevent curl from adding it
|
||||
if (!$request->hasHeader('Expect')) {
|
||||
$curlOptions[CURLOPT_HTTPHEADER][] = 'Expect:';
|
||||
}
|
||||
}
|
||||
|
||||
// If a Content-Length header was specified but we want to allow curl to set one for us
|
||||
if (null !== $tempContentLength) {
|
||||
$request->removeHeader('Content-Length');
|
||||
}
|
||||
|
||||
// Set custom cURL options
|
||||
foreach ($requestCurlOptions->toArray() as $key => $value) {
|
||||
if (is_numeric($key)) {
|
||||
$curlOptions[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
// Do not set an Accept header by default
|
||||
if (!isset($curlOptions[CURLOPT_ENCODING])) {
|
||||
$curlOptions[CURLOPT_HTTPHEADER][] = 'Accept:';
|
||||
}
|
||||
|
||||
// Add any custom headers to the request. Empty headers will cause curl to not send the header at all.
|
||||
foreach ($request->getHeaderLines() as $line) {
|
||||
$curlOptions[CURLOPT_HTTPHEADER][] = $line;
|
||||
}
|
||||
|
||||
// Add the content-length header back if it was temporarily removed
|
||||
if ($tempContentLength) {
|
||||
$request->setHeader('Content-Length', $tempContentLength);
|
||||
}
|
||||
|
||||
// Apply the options to a new cURL handle.
|
||||
$handle = curl_init();
|
||||
|
||||
// Enable the progress function if the 'progress' param was set
|
||||
if ($requestCurlOptions->get('progress')) {
|
||||
// Wrap the function in a function that provides the curl handle to the mediator's progress function
|
||||
// Using this rather than injecting the handle into the mediator prevents a circular reference
|
||||
$curlOptions[CURLOPT_PROGRESSFUNCTION] = function () use ($mediator, $handle) {
|
||||
$args = func_get_args();
|
||||
$args[] = $handle;
|
||||
call_user_func_array(array($mediator, 'progress'), $args);
|
||||
};
|
||||
$curlOptions[CURLOPT_NOPROGRESS] = false;
|
||||
}
|
||||
|
||||
curl_setopt_array($handle, $curlOptions);
|
||||
|
||||
return new static($handle, $curlOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new CurlHandle object that wraps a cURL handle
|
||||
*
|
||||
* @param resource $handle Configured cURL handle resource
|
||||
* @param Collection|array $options Curl options to use with the handle
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function __construct($handle, $options)
|
||||
{
|
||||
if (!is_resource($handle)) {
|
||||
throw new InvalidArgumentException('Invalid handle provided');
|
||||
}
|
||||
if (is_array($options)) {
|
||||
$this->options = new Collection($options);
|
||||
} elseif ($options instanceof Collection) {
|
||||
$this->options = $options;
|
||||
} else {
|
||||
throw new InvalidArgumentException('Expected array or Collection');
|
||||
}
|
||||
$this->handle = $handle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
$this->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the curl handle
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
if (is_resource($this->handle)) {
|
||||
curl_close($this->handle);
|
||||
}
|
||||
$this->handle = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the handle is available and still OK
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isAvailable()
|
||||
{
|
||||
return is_resource($this->handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the last error that occurred on the cURL handle
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getError()
|
||||
{
|
||||
return $this->isAvailable() ? curl_error($this->handle) : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the last error number that occurred on the cURL handle
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getErrorNo()
|
||||
{
|
||||
if ($this->errorNo) {
|
||||
return $this->errorNo;
|
||||
}
|
||||
|
||||
return $this->isAvailable() ? curl_errno($this->handle) : CURLE_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the curl error number
|
||||
*
|
||||
* @param int $error Error number to set
|
||||
*
|
||||
* @return CurlHandle
|
||||
*/
|
||||
public function setErrorNo($error)
|
||||
{
|
||||
$this->errorNo = $error;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cURL curl_getinfo data
|
||||
*
|
||||
* @param int $option Option to retrieve. Pass null to retrieve all data as an array.
|
||||
*
|
||||
* @return array|mixed
|
||||
*/
|
||||
public function getInfo($option = null)
|
||||
{
|
||||
if (!is_resource($this->handle)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (null !== $option) {
|
||||
return curl_getinfo($this->handle, $option) ?: null;
|
||||
}
|
||||
|
||||
return curl_getinfo($this->handle) ?: array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the stderr output
|
||||
*
|
||||
* @param bool $asResource Set to TRUE to get an fopen resource
|
||||
*
|
||||
* @return string|resource|null
|
||||
*/
|
||||
public function getStderr($asResource = false)
|
||||
{
|
||||
$stderr = $this->getOptions()->get(CURLOPT_STDERR);
|
||||
if (!$stderr) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($asResource) {
|
||||
return $stderr;
|
||||
}
|
||||
|
||||
fseek($stderr, 0);
|
||||
$e = stream_get_contents($stderr);
|
||||
fseek($stderr, 0, SEEK_END);
|
||||
|
||||
return $e;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the URL that this handle is connecting to
|
||||
*
|
||||
* @return Url
|
||||
*/
|
||||
public function getUrl()
|
||||
{
|
||||
return Url::factory($this->options->get(CURLOPT_URL));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the wrapped curl handle
|
||||
*
|
||||
* @return resource|null Returns the cURL handle or null if it was closed
|
||||
*/
|
||||
public function getHandle()
|
||||
{
|
||||
return $this->isAvailable() ? $this->handle : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the cURL setopt options of the handle. Changing values in the return object will have no effect on the curl
|
||||
* handle after it is created.
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getOptions()
|
||||
{
|
||||
return $this->options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a request based on the log messages of the CurlHandle
|
||||
*
|
||||
* @param RequestInterface $request Request to update
|
||||
*/
|
||||
public function updateRequestFromTransfer(RequestInterface $request)
|
||||
{
|
||||
if (!$request->getResponse()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Update the transfer stats of the response
|
||||
$request->getResponse()->setInfo($this->getInfo());
|
||||
|
||||
if (!$log = $this->getStderr(true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse the cURL stderr output for outgoing requests
|
||||
$headers = '';
|
||||
fseek($log, 0);
|
||||
while (($line = fgets($log)) !== false) {
|
||||
if ($line && $line[0] == '>') {
|
||||
$headers = substr(trim($line), 2) . "\r\n";
|
||||
while (($line = fgets($log)) !== false) {
|
||||
if ($line[0] == '*' || $line[0] == '<') {
|
||||
break;
|
||||
} else {
|
||||
$headers .= trim($line) . "\r\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add request headers to the request exactly as they were sent
|
||||
if ($headers) {
|
||||
$parsed = ParserRegistry::getInstance()->getParser('message')->parseRequest($headers);
|
||||
if (!empty($parsed['headers'])) {
|
||||
$request->setHeaders(array());
|
||||
foreach ($parsed['headers'] as $name => $value) {
|
||||
$request->setHeader($name, $value);
|
||||
}
|
||||
}
|
||||
if (!empty($parsed['version'])) {
|
||||
$request->setProtocolVersion($parsed['version']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the config and replace curl.* configurators into the constant based values so it can be used elsewhere
|
||||
*
|
||||
* @param array|Collection $config The configuration we want to parse
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function parseCurlConfig($config)
|
||||
{
|
||||
$curlOptions = array();
|
||||
foreach ($config as $key => $value) {
|
||||
if (is_string($key) && defined($key)) {
|
||||
// Convert constants represented as string to constant int values
|
||||
$key = constant($key);
|
||||
}
|
||||
if (is_string($value) && defined($value)) {
|
||||
$value = constant($value);
|
||||
}
|
||||
$curlOptions[$key] = $value;
|
||||
}
|
||||
|
||||
return $curlOptions;
|
||||
}
|
||||
}
|
|
@ -1,390 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http\Curl;
|
||||
|
||||
use Guzzle\Common\AbstractHasDispatcher;
|
||||
use Guzzle\Common\Event;
|
||||
use Guzzle\Http\Exception\MultiTransferException;
|
||||
use Guzzle\Http\Exception\CurlException;
|
||||
use Guzzle\Http\Message\RequestInterface;
|
||||
|
||||
/**
|
||||
* Send {@see RequestInterface} objects in parallel using curl_multi
|
||||
*/
|
||||
class CurlMulti extends AbstractHasDispatcher implements CurlMultiInterface
|
||||
{
|
||||
/** @var resource cURL multi handle. */
|
||||
protected $multiHandle;
|
||||
|
||||
/** @var array Attached {@see RequestInterface} objects. */
|
||||
protected $requests;
|
||||
|
||||
/** @var \SplObjectStorage RequestInterface to CurlHandle hash */
|
||||
protected $handles;
|
||||
|
||||
/** @var array Hash mapping curl handle resource IDs to request objects */
|
||||
protected $resourceHash;
|
||||
|
||||
/** @var array Queued exceptions */
|
||||
protected $exceptions = array();
|
||||
|
||||
/** @var array Requests that succeeded */
|
||||
protected $successful = array();
|
||||
|
||||
/** @var array cURL multi error values and codes */
|
||||
protected $multiErrors = array(
|
||||
CURLM_BAD_HANDLE => array('CURLM_BAD_HANDLE', 'The passed-in handle is not a valid CURLM handle.'),
|
||||
CURLM_BAD_EASY_HANDLE => array('CURLM_BAD_EASY_HANDLE', "An easy handle was not good/valid. It could mean that it isn't an easy handle at all, or possibly that the handle already is in used by this or another multi handle."),
|
||||
CURLM_OUT_OF_MEMORY => array('CURLM_OUT_OF_MEMORY', 'You are doomed.'),
|
||||
CURLM_INTERNAL_ERROR => array('CURLM_INTERNAL_ERROR', 'This can only be returned if libcurl bugs. Please report it to us!')
|
||||
);
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->multiHandle = curl_multi_init();
|
||||
// @codeCoverageIgnoreStart
|
||||
if ($this->multiHandle === false) {
|
||||
throw new CurlException('Unable to create multi handle');
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
$this->reset();
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
if (is_resource($this->multiHandle)) {
|
||||
curl_multi_close($this->multiHandle);
|
||||
}
|
||||
}
|
||||
|
||||
public function add(RequestInterface $request)
|
||||
{
|
||||
$this->requests[] = $request;
|
||||
// If requests are currently transferring and this is async, then the
|
||||
// request must be prepared now as the send() method is not called.
|
||||
$this->beforeSend($request);
|
||||
$this->dispatch(self::ADD_REQUEST, array('request' => $request));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function all()
|
||||
{
|
||||
return $this->requests;
|
||||
}
|
||||
|
||||
public function remove(RequestInterface $request)
|
||||
{
|
||||
$this->removeHandle($request);
|
||||
foreach ($this->requests as $i => $r) {
|
||||
if ($request === $r) {
|
||||
unset($this->requests[$i]);
|
||||
$this->requests = array_values($this->requests);
|
||||
$this->dispatch(self::REMOVE_REQUEST, array('request' => $request));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function reset($hard = false)
|
||||
{
|
||||
// Remove each request
|
||||
if ($this->requests) {
|
||||
foreach ($this->requests as $request) {
|
||||
$this->remove($request);
|
||||
}
|
||||
}
|
||||
|
||||
$this->handles = new \SplObjectStorage();
|
||||
$this->requests = $this->resourceHash = $this->exceptions = $this->successful = array();
|
||||
}
|
||||
|
||||
public function send()
|
||||
{
|
||||
$this->perform();
|
||||
$exceptions = $this->exceptions;
|
||||
$successful = $this->successful;
|
||||
$this->reset();
|
||||
|
||||
if ($exceptions) {
|
||||
$this->throwMultiException($exceptions, $successful);
|
||||
}
|
||||
}
|
||||
|
||||
public function count()
|
||||
{
|
||||
return count($this->requests);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build and throw a MultiTransferException
|
||||
*
|
||||
* @param array $exceptions Exceptions encountered
|
||||
* @param array $successful Successful requests
|
||||
* @throws MultiTransferException
|
||||
*/
|
||||
protected function throwMultiException(array $exceptions, array $successful)
|
||||
{
|
||||
$multiException = new MultiTransferException('Errors during multi transfer');
|
||||
|
||||
while ($e = array_shift($exceptions)) {
|
||||
$multiException->add($e['exception']);
|
||||
$multiException->addFailedRequest($e['request']);
|
||||
}
|
||||
|
||||
// Add successful requests
|
||||
foreach ($successful as $request) {
|
||||
if (!$multiException->containsRequest($request)) {
|
||||
$multiException->addSuccessfulRequest($request);
|
||||
}
|
||||
}
|
||||
|
||||
throw $multiException;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare for sending
|
||||
*
|
||||
* @param RequestInterface $request Request to prepare
|
||||
* @throws \Exception on error preparing the request
|
||||
*/
|
||||
protected function beforeSend(RequestInterface $request)
|
||||
{
|
||||
try {
|
||||
$state = $request->setState(RequestInterface::STATE_TRANSFER);
|
||||
if ($state == RequestInterface::STATE_TRANSFER) {
|
||||
// Add the request curl handle to the multi handle
|
||||
$this->checkCurlResult(curl_multi_add_handle($this->multiHandle, $this->createCurlHandle($request)->getHandle()));
|
||||
} else {
|
||||
// Requests might decide they don't need to be sent just before transfer (e.g. CachePlugin)
|
||||
$this->remove($request);
|
||||
if ($state == RequestInterface::STATE_COMPLETE) {
|
||||
$this->successful[] = $request;
|
||||
}
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
// Queue the exception to be thrown when sent
|
||||
$this->removeErroredRequest($request, $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a curl handle for a request
|
||||
*
|
||||
* @param RequestInterface $request Request
|
||||
*
|
||||
* @return CurlHandle
|
||||
*/
|
||||
protected function createCurlHandle(RequestInterface $request)
|
||||
{
|
||||
$wrapper = CurlHandle::factory($request);
|
||||
$this->handles[$request] = $wrapper;
|
||||
$this->resourceHash[(int) $wrapper->getHandle()] = $request;
|
||||
|
||||
return $wrapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data from the multi handle
|
||||
*/
|
||||
protected function perform()
|
||||
{
|
||||
if (!$this->requests) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialize the handles with a very quick select timeout
|
||||
$active = $mrc = null;
|
||||
$this->executeHandles($active, $mrc, 0.001);
|
||||
$event = new Event(array('curl_multi' => $this));
|
||||
$this->processMessages();
|
||||
|
||||
while ($this->requests) {
|
||||
|
||||
// Notify each request as polling
|
||||
$blocking = $total = 0;
|
||||
foreach ($this->requests as $request) {
|
||||
++$total;
|
||||
$event['request'] = $request;
|
||||
$request->getEventDispatcher()->dispatch(self::POLLING_REQUEST, $event);
|
||||
// The blocking variable just has to be non-falsey to block the loop
|
||||
if ($request->getParams()->hasKey(self::BLOCKING)) {
|
||||
++$blocking;
|
||||
}
|
||||
}
|
||||
|
||||
if ($blocking == $total) {
|
||||
// Sleep to prevent eating CPU because no requests are actually pending a select call
|
||||
usleep(500);
|
||||
} else {
|
||||
do {
|
||||
$this->executeHandles($active, $mrc, 1);
|
||||
} while ($active);
|
||||
}
|
||||
$this->processMessages();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process any received curl multi messages
|
||||
*/
|
||||
private function processMessages()
|
||||
{
|
||||
// Get messages from curl handles
|
||||
while ($done = curl_multi_info_read($this->multiHandle)) {
|
||||
try {
|
||||
$request = $this->resourceHash[(int) $done['handle']];
|
||||
$this->processResponse($request, $this->handles[$request], $done);
|
||||
$this->successful[] = $request;
|
||||
} catch (MultiTransferException $e) {
|
||||
$this->removeErroredRequest($request, $e, false);
|
||||
throw $e;
|
||||
} catch (\Exception $e) {
|
||||
$this->removeErroredRequest($request, $e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute and select curl handles until there is activity
|
||||
*
|
||||
* @param int $active Active value to update
|
||||
* @param int $mrc Multi result value to update
|
||||
* @param int $timeout Select timeout in seconds
|
||||
*/
|
||||
private function executeHandles(&$active, &$mrc, $timeout = 1)
|
||||
{
|
||||
do {
|
||||
$mrc = curl_multi_exec($this->multiHandle, $active);
|
||||
} while ($mrc == CURLM_CALL_MULTI_PERFORM && $active);
|
||||
$this->checkCurlResult($mrc);
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
// Select the curl handles until there is any activity on any of the open file descriptors
|
||||
// See https://github.com/php/php-src/blob/master/ext/curl/multi.c#L170
|
||||
if ($active && $mrc == CURLM_OK && curl_multi_select($this->multiHandle, $timeout) == -1) {
|
||||
// Perform a usleep if a previously executed select returned -1
|
||||
// @see https://bugs.php.net/bug.php?id=61141
|
||||
usleep(100);
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a request that encountered an exception
|
||||
*
|
||||
* @param RequestInterface $request Request to remove
|
||||
* @param \Exception $e Exception encountered
|
||||
* @param bool $buffer Set to false to not buffer the exception
|
||||
*/
|
||||
protected function removeErroredRequest(RequestInterface $request, \Exception $e = null, $buffer = true)
|
||||
{
|
||||
if ($buffer) {
|
||||
$this->exceptions[] = array('request' => $request, 'exception' => $e);
|
||||
}
|
||||
|
||||
$this->remove($request);
|
||||
$this->dispatch(self::MULTI_EXCEPTION, array('exception' => $e, 'all_exceptions' => $this->exceptions));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for errors and fix headers of a request based on a curl response
|
||||
*
|
||||
* @param RequestInterface $request Request to process
|
||||
* @param CurlHandle $handle Curl handle object
|
||||
* @param array $curl Array returned from curl_multi_info_read
|
||||
*
|
||||
* @throws CurlException on Curl error
|
||||
*/
|
||||
protected function processResponse(RequestInterface $request, CurlHandle $handle, array $curl)
|
||||
{
|
||||
// Set the transfer stats on the response
|
||||
$handle->updateRequestFromTransfer($request);
|
||||
// Check if a cURL exception occurred, and if so, notify things
|
||||
$curlException = $this->isCurlException($request, $handle, $curl);
|
||||
|
||||
// Always remove completed curl handles. They can be added back again
|
||||
// via events if needed (e.g. ExponentialBackoffPlugin)
|
||||
$this->removeHandle($request);
|
||||
|
||||
if (!$curlException) {
|
||||
$state = $request->setState(RequestInterface::STATE_COMPLETE, array('handle' => $handle));
|
||||
// Only remove the request if it wasn't resent as a result of the state change
|
||||
if ($state != RequestInterface::STATE_TRANSFER) {
|
||||
$this->remove($request);
|
||||
}
|
||||
} else {
|
||||
// Set the state of the request to an error
|
||||
$state = $request->setState(RequestInterface::STATE_ERROR, array('exception' => $curlException));
|
||||
// Allow things to ignore the error if possible
|
||||
if ($state != RequestInterface::STATE_TRANSFER) {
|
||||
$this->remove($request);
|
||||
}
|
||||
// The error was not handled, so fail
|
||||
if ($state == RequestInterface::STATE_ERROR) {
|
||||
/** @var CurlException $curlException */
|
||||
throw $curlException;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a curl handle from the curl multi object
|
||||
*
|
||||
* @param RequestInterface $request Request that owns the handle
|
||||
*/
|
||||
protected function removeHandle(RequestInterface $request)
|
||||
{
|
||||
if (isset($this->handles[$request])) {
|
||||
$handle = $this->handles[$request];
|
||||
unset($this->handles[$request]);
|
||||
unset($this->resourceHash[(int) $handle->getHandle()]);
|
||||
curl_multi_remove_handle($this->multiHandle, $handle->getHandle());
|
||||
$handle->close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a cURL transfer resulted in what should be an exception
|
||||
*
|
||||
* @param RequestInterface $request Request to check
|
||||
* @param CurlHandle $handle Curl handle object
|
||||
* @param array $curl Array returned from curl_multi_info_read
|
||||
*
|
||||
* @return CurlException|bool
|
||||
*/
|
||||
private function isCurlException(RequestInterface $request, CurlHandle $handle, array $curl)
|
||||
{
|
||||
if (CURLM_OK == $curl['result'] || CURLM_CALL_MULTI_PERFORM == $curl['result']) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$handle->setErrorNo($curl['result']);
|
||||
$e = new CurlException(sprintf('[curl] %s: %s [url] %s',
|
||||
$handle->getErrorNo(), $handle->getError(), $handle->getUrl()));
|
||||
$e->setCurlHandle($handle)
|
||||
->setRequest($request)
|
||||
->setCurlInfo($handle->getInfo())
|
||||
->setError($handle->getError(), $handle->getErrorNo());
|
||||
|
||||
return $e;
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw an exception for a cURL multi response if needed
|
||||
*
|
||||
* @param int $code Curl response code
|
||||
* @throws CurlException
|
||||
*/
|
||||
private function checkCurlResult($code)
|
||||
{
|
||||
if ($code != CURLM_OK && $code != CURLM_CALL_MULTI_PERFORM) {
|
||||
throw new CurlException(isset($this->multiErrors[$code])
|
||||
? "cURL error: {$code} ({$this->multiErrors[$code][0]}): cURL message: {$this->multiErrors[$code][1]}"
|
||||
: 'Unexpected cURL error: ' . $code
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http\Curl;
|
||||
|
||||
use Guzzle\Common\HasDispatcherInterface;
|
||||
use Guzzle\Common\Exception\ExceptionCollection;
|
||||
use Guzzle\Http\Message\RequestInterface;
|
||||
|
||||
/**
|
||||
* Interface for sending a pool of {@see RequestInterface} objects in parallel
|
||||
*/
|
||||
interface CurlMultiInterface extends \Countable, HasDispatcherInterface
|
||||
{
|
||||
const POLLING_REQUEST = 'curl_multi.polling_request';
|
||||
const ADD_REQUEST = 'curl_multi.add_request';
|
||||
const REMOVE_REQUEST = 'curl_multi.remove_request';
|
||||
const MULTI_EXCEPTION = 'curl_multi.exception';
|
||||
const BLOCKING = 'curl_multi.blocking';
|
||||
|
||||
/**
|
||||
* Add a request to the pool.
|
||||
*
|
||||
* @param RequestInterface $request Request to add
|
||||
*
|
||||
* @return CurlMultiInterface
|
||||
*/
|
||||
public function add(RequestInterface $request);
|
||||
|
||||
/**
|
||||
* Get an array of attached {@see RequestInterface} objects
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function all();
|
||||
|
||||
/**
|
||||
* Remove a request from the pool.
|
||||
*
|
||||
* @param RequestInterface $request Request to remove
|
||||
*
|
||||
* @return bool Returns true on success or false on failure
|
||||
*/
|
||||
public function remove(RequestInterface $request);
|
||||
|
||||
/**
|
||||
* Reset the state and remove any attached RequestInterface objects
|
||||
*
|
||||
* @param bool $hard Set to true to close and reopen any open multi handles
|
||||
*/
|
||||
public function reset($hard = false);
|
||||
|
||||
/**
|
||||
* Send a pool of {@see RequestInterface} requests.
|
||||
*
|
||||
* @throws ExceptionCollection if any requests threw exceptions during the transfer.
|
||||
*/
|
||||
public function send();
|
||||
}
|
|
@ -1,147 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http\Curl;
|
||||
|
||||
use Guzzle\Common\AbstractHasDispatcher;
|
||||
use Guzzle\Http\Message\RequestInterface;
|
||||
|
||||
/**
|
||||
* Proxies requests and connections to a pool of internal curl_multi handles. Each recursive call will add requests
|
||||
* to the next available CurlMulti handle.
|
||||
*/
|
||||
class CurlMultiProxy extends AbstractHasDispatcher implements CurlMultiInterface
|
||||
{
|
||||
protected $handles = array();
|
||||
protected $groups = array();
|
||||
protected $queued = array();
|
||||
protected $maxHandles;
|
||||
|
||||
/**
|
||||
* @param int $maxHandles The maximum number of idle CurlMulti handles to allow to remain open
|
||||
*/
|
||||
public function __construct($maxHandles = 3)
|
||||
{
|
||||
$this->maxHandles = $maxHandles;
|
||||
// You can get some weird "Too many open files" errors when sending a large amount of requests in parallel.
|
||||
// These two statements autoload classes before a system runs out of file descriptors so that you can get back
|
||||
// valuable error messages if you run out.
|
||||
class_exists('Guzzle\Http\Message\Response');
|
||||
class_exists('Guzzle\Http\Exception\CurlException');
|
||||
}
|
||||
|
||||
public function add(RequestInterface $request)
|
||||
{
|
||||
$this->queued[] = $request;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function all()
|
||||
{
|
||||
$requests = $this->queued;
|
||||
foreach ($this->handles as $handle) {
|
||||
$requests = array_merge($requests, $handle->all());
|
||||
}
|
||||
|
||||
return $requests;
|
||||
}
|
||||
|
||||
public function remove(RequestInterface $request)
|
||||
{
|
||||
foreach ($this->queued as $i => $r) {
|
||||
if ($request === $r) {
|
||||
unset($this->queued[$i]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->handles as $handle) {
|
||||
if ($handle->remove($request)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function reset($hard = false)
|
||||
{
|
||||
$this->queued = array();
|
||||
$this->groups = array();
|
||||
foreach ($this->handles as $handle) {
|
||||
$handle->reset();
|
||||
}
|
||||
if ($hard) {
|
||||
$this->handles = array();
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function send()
|
||||
{
|
||||
if ($this->queued) {
|
||||
$group = $this->getAvailableHandle();
|
||||
// Add this handle to a list of handles than is claimed
|
||||
$this->groups[] = $group;
|
||||
while ($request = array_shift($this->queued)) {
|
||||
$group->add($request);
|
||||
}
|
||||
try {
|
||||
$group->send();
|
||||
array_pop($this->groups);
|
||||
$this->cleanupHandles();
|
||||
} catch (\Exception $e) {
|
||||
// Remove the group and cleanup if an exception was encountered and no more requests in group
|
||||
if (!$group->count()) {
|
||||
array_pop($this->groups);
|
||||
$this->cleanupHandles();
|
||||
}
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function count()
|
||||
{
|
||||
return count($this->all());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an existing available CurlMulti handle or create a new one
|
||||
*
|
||||
* @return CurlMulti
|
||||
*/
|
||||
protected function getAvailableHandle()
|
||||
{
|
||||
// Grab a handle that is not claimed
|
||||
foreach ($this->handles as $h) {
|
||||
if (!in_array($h, $this->groups, true)) {
|
||||
return $h;
|
||||
}
|
||||
}
|
||||
|
||||
// All are claimed, so create one
|
||||
$handle = new CurlMulti();
|
||||
$handle->setEventDispatcher($this->getEventDispatcher());
|
||||
$this->handles[] = $handle;
|
||||
|
||||
return $handle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trims down unused CurlMulti handles to limit the number of open connections
|
||||
*/
|
||||
protected function cleanupHandles()
|
||||
{
|
||||
if ($diff = max(0, count($this->handles) - $this->maxHandles)) {
|
||||
for ($i = count($this->handles) - 1; $i > 0 && $diff > 0; $i--) {
|
||||
if (!count($this->handles[$i])) {
|
||||
unset($this->handles[$i]);
|
||||
$diff--;
|
||||
}
|
||||
}
|
||||
$this->handles = array_values($this->handles);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http\Curl;
|
||||
|
||||
/**
|
||||
* Class used for querying curl_version data
|
||||
*/
|
||||
class CurlVersion
|
||||
{
|
||||
/** @var array curl_version() information */
|
||||
protected $version;
|
||||
|
||||
/** @var CurlVersion */
|
||||
protected static $instance;
|
||||
|
||||
/** @var string Default user agent */
|
||||
protected $userAgent;
|
||||
|
||||
/**
|
||||
* @return CurlVersion
|
||||
*/
|
||||
public static function getInstance()
|
||||
{
|
||||
if (!self::$instance) {
|
||||
self::$instance = new self();
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the curl_version() data
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAll()
|
||||
{
|
||||
if (!$this->version) {
|
||||
$this->version = curl_version();
|
||||
}
|
||||
|
||||
return $this->version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a specific type of curl information
|
||||
*
|
||||
* @param string $type Version information to retrieve. This value is one of:
|
||||
* - version_number: cURL 24 bit version number
|
||||
* - version: cURL version number, as a string
|
||||
* - ssl_version_number: OpenSSL 24 bit version number
|
||||
* - ssl_version: OpenSSL version number, as a string
|
||||
* - libz_version: zlib version number, as a string
|
||||
* - host: Information about the host where cURL was built
|
||||
* - features: A bitmask of the CURL_VERSION_XXX constants
|
||||
* - protocols: An array of protocols names supported by cURL
|
||||
*
|
||||
* @return string|float|bool if the $type is found, and false if not found
|
||||
*/
|
||||
public function get($type)
|
||||
{
|
||||
$version = $this->getAll();
|
||||
|
||||
return isset($version[$type]) ? $version[$type] : false;
|
||||
}
|
||||
}
|
|
@ -1,142 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http\Curl;
|
||||
|
||||
use Guzzle\Http\Message\RequestInterface;
|
||||
use Guzzle\Http\EntityBody;
|
||||
use Guzzle\Http\Message\Response;
|
||||
|
||||
/**
|
||||
* Mediator between curl handles and request objects
|
||||
*/
|
||||
class RequestMediator
|
||||
{
|
||||
/** @var RequestInterface */
|
||||
protected $request;
|
||||
|
||||
/** @var bool Whether or not to emit read/write events */
|
||||
protected $emitIo;
|
||||
|
||||
/**
|
||||
* @param RequestInterface $request Request to mediate
|
||||
* @param bool $emitIo Set to true to dispatch events on input and output
|
||||
*/
|
||||
public function __construct(RequestInterface $request, $emitIo = false)
|
||||
{
|
||||
$this->request = $request;
|
||||
$this->emitIo = $emitIo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Receive a response header from curl
|
||||
*
|
||||
* @param resource $curl Curl handle
|
||||
* @param string $header Received header
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function receiveResponseHeader($curl, $header)
|
||||
{
|
||||
static $normalize = array("\r", "\n");
|
||||
$length = strlen($header);
|
||||
$header = str_replace($normalize, '', $header);
|
||||
|
||||
if (strpos($header, 'HTTP/') === 0) {
|
||||
|
||||
$startLine = explode(' ', $header, 3);
|
||||
$code = $startLine[1];
|
||||
$status = isset($startLine[2]) ? $startLine[2] : '';
|
||||
|
||||
// Only download the body of the response to the specified response
|
||||
// body when a successful response is received.
|
||||
if ($code >= 200 && $code < 300) {
|
||||
$body = $this->request->getResponseBody();
|
||||
} else {
|
||||
$body = EntityBody::factory();
|
||||
}
|
||||
|
||||
$response = new Response($code, null, $body);
|
||||
$response->setStatus($code, $status);
|
||||
$this->request->startResponse($response);
|
||||
|
||||
$this->request->dispatch('request.receive.status_line', array(
|
||||
'request' => $this,
|
||||
'line' => $header,
|
||||
'status_code' => $code,
|
||||
'reason_phrase' => $status
|
||||
));
|
||||
|
||||
} elseif ($pos = strpos($header, ':')) {
|
||||
$this->request->getResponse()->addHeader(
|
||||
trim(substr($header, 0, $pos)),
|
||||
trim(substr($header, $pos + 1))
|
||||
);
|
||||
}
|
||||
|
||||
return $length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Received a progress notification
|
||||
*
|
||||
* @param int $downloadSize Total download size
|
||||
* @param int $downloaded Amount of bytes downloaded
|
||||
* @param int $uploadSize Total upload size
|
||||
* @param int $uploaded Amount of bytes uploaded
|
||||
* @param resource $handle CurlHandle object
|
||||
*/
|
||||
public function progress($downloadSize, $downloaded, $uploadSize, $uploaded, $handle = null)
|
||||
{
|
||||
$this->request->dispatch('curl.callback.progress', array(
|
||||
'request' => $this->request,
|
||||
'handle' => $handle,
|
||||
'download_size' => $downloadSize,
|
||||
'downloaded' => $downloaded,
|
||||
'upload_size' => $uploadSize,
|
||||
'uploaded' => $uploaded
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Write data to the response body of a request
|
||||
*
|
||||
* @param resource $curl Curl handle
|
||||
* @param string $write Data that was received
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function writeResponseBody($curl, $write)
|
||||
{
|
||||
if ($this->emitIo) {
|
||||
$this->request->dispatch('curl.callback.write', array(
|
||||
'request' => $this->request,
|
||||
'write' => $write
|
||||
));
|
||||
}
|
||||
|
||||
return $this->request->getResponse()->getBody()->write($write);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read data from the request body and send it to curl
|
||||
*
|
||||
* @param resource $ch Curl handle
|
||||
* @param resource $fd File descriptor
|
||||
* @param int $length Amount of data to read
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function readRequestBody($ch, $fd, $length)
|
||||
{
|
||||
if (!($body = $this->request->getBody())) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$read = (string) $body->read($length);
|
||||
if ($this->emitIo) {
|
||||
$this->request->dispatch('curl.callback.read', array('request' => $this->request, 'read' => $read));
|
||||
}
|
||||
|
||||
return $read;
|
||||
}
|
||||
}
|
|
@ -1,201 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http;
|
||||
|
||||
use Guzzle\Common\Version;
|
||||
use Guzzle\Stream\Stream;
|
||||
use Guzzle\Common\Exception\InvalidArgumentException;
|
||||
use Guzzle\Http\Mimetypes;
|
||||
|
||||
/**
|
||||
* Entity body used with an HTTP request or response
|
||||
*/
|
||||
class EntityBody extends Stream implements EntityBodyInterface
|
||||
{
|
||||
/** @var bool Content-Encoding of the entity body if known */
|
||||
protected $contentEncoding = false;
|
||||
|
||||
/** @var callable Method to invoke for rewinding a stream */
|
||||
protected $rewindFunction;
|
||||
|
||||
/**
|
||||
* Create a new EntityBody based on the input type
|
||||
*
|
||||
* @param resource|string|EntityBody $resource Entity body data
|
||||
* @param int $size Size of the data contained in the resource
|
||||
*
|
||||
* @return EntityBody
|
||||
* @throws InvalidArgumentException if the $resource arg is not a resource or string
|
||||
*/
|
||||
public static function factory($resource = '', $size = null)
|
||||
{
|
||||
if ($resource instanceof EntityBodyInterface) {
|
||||
return $resource;
|
||||
}
|
||||
|
||||
switch (gettype($resource)) {
|
||||
case 'string':
|
||||
return self::fromString($resource);
|
||||
case 'resource':
|
||||
return new static($resource, $size);
|
||||
case 'object':
|
||||
if (method_exists($resource, '__toString')) {
|
||||
return self::fromString((string) $resource);
|
||||
}
|
||||
break;
|
||||
case 'array':
|
||||
return self::fromString(http_build_query($resource));
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException('Invalid resource type');
|
||||
}
|
||||
|
||||
public function setRewindFunction($callable)
|
||||
{
|
||||
if (!is_callable($callable)) {
|
||||
throw new InvalidArgumentException('Must specify a callable');
|
||||
}
|
||||
|
||||
$this->rewindFunction = $callable;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function rewind()
|
||||
{
|
||||
return $this->rewindFunction ? call_user_func($this->rewindFunction, $this) : parent::rewind();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new EntityBody from a string
|
||||
*
|
||||
* @param string $string String of data
|
||||
*
|
||||
* @return EntityBody
|
||||
*/
|
||||
public static function fromString($string)
|
||||
{
|
||||
$stream = fopen('php://temp', 'r+');
|
||||
if ($string !== '') {
|
||||
fwrite($stream, $string);
|
||||
rewind($stream);
|
||||
}
|
||||
|
||||
return new static($stream);
|
||||
}
|
||||
|
||||
public function compress($filter = 'zlib.deflate')
|
||||
{
|
||||
$result = $this->handleCompression($filter);
|
||||
$this->contentEncoding = $result ? $filter : false;
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function uncompress($filter = 'zlib.inflate')
|
||||
{
|
||||
$offsetStart = 0;
|
||||
|
||||
// When inflating gzipped data, the first 10 bytes must be stripped
|
||||
// if a gzip header is present
|
||||
if ($filter == 'zlib.inflate') {
|
||||
// @codeCoverageIgnoreStart
|
||||
if (!$this->isReadable() || ($this->isConsumed() && !$this->isSeekable())) {
|
||||
return false;
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
if (stream_get_contents($this->stream, 3, 0) === "\x1f\x8b\x08") {
|
||||
$offsetStart = 10;
|
||||
}
|
||||
}
|
||||
|
||||
$this->contentEncoding = false;
|
||||
|
||||
return $this->handleCompression($filter, $offsetStart);
|
||||
}
|
||||
|
||||
public function getContentLength()
|
||||
{
|
||||
return $this->getSize();
|
||||
}
|
||||
|
||||
public function getContentType()
|
||||
{
|
||||
return $this->getUri() ? Mimetypes::getInstance()->fromFilename($this->getUri()) : null;
|
||||
}
|
||||
|
||||
public function getContentMd5($rawOutput = false, $base64Encode = false)
|
||||
{
|
||||
if ($hash = self::getHash($this, 'md5', $rawOutput)) {
|
||||
return $hash && $base64Encode ? base64_encode($hash) : $hash;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the MD5 hash of an entity body
|
||||
*
|
||||
* @param EntityBodyInterface $body Entity body to calculate the hash for
|
||||
* @param bool $rawOutput Whether or not to use raw output
|
||||
* @param bool $base64Encode Whether or not to base64 encode raw output (only if raw output is true)
|
||||
*
|
||||
* @return bool|string Returns an MD5 string on success or FALSE on failure
|
||||
* @deprecated This will be deprecated soon
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public static function calculateMd5(EntityBodyInterface $body, $rawOutput = false, $base64Encode = false)
|
||||
{
|
||||
Version::warn(__CLASS__ . ' is deprecated. Use getContentMd5()');
|
||||
return $body->getContentMd5($rawOutput, $base64Encode);
|
||||
}
|
||||
|
||||
public function setStreamFilterContentEncoding($streamFilterContentEncoding)
|
||||
{
|
||||
$this->contentEncoding = $streamFilterContentEncoding;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getContentEncoding()
|
||||
{
|
||||
return strtr($this->contentEncoding, array(
|
||||
'zlib.deflate' => 'gzip',
|
||||
'bzip2.compress' => 'compress'
|
||||
)) ?: false;
|
||||
}
|
||||
|
||||
protected function handleCompression($filter, $offsetStart = 0)
|
||||
{
|
||||
// @codeCoverageIgnoreStart
|
||||
if (!$this->isReadable() || ($this->isConsumed() && !$this->isSeekable())) {
|
||||
return false;
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
$handle = fopen('php://temp', 'r+');
|
||||
$filter = @stream_filter_append($handle, $filter, STREAM_FILTER_WRITE);
|
||||
if (!$filter) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Seek to the offset start if possible
|
||||
$this->seek($offsetStart);
|
||||
while ($data = fread($this->stream, 8096)) {
|
||||
fwrite($handle, $data);
|
||||
}
|
||||
|
||||
fclose($this->stream);
|
||||
$this->stream = $handle;
|
||||
stream_filter_remove($filter);
|
||||
$stat = fstat($this->stream);
|
||||
$this->size = $stat['size'];
|
||||
$this->rebuildCache();
|
||||
$this->seek(0);
|
||||
|
||||
// Remove any existing rewind function as the underlying stream has been replaced
|
||||
$this->rewindFunction = null;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,73 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http;
|
||||
|
||||
use Guzzle\Stream\StreamInterface;
|
||||
|
||||
/**
|
||||
* Entity body used with an HTTP request or response
|
||||
*/
|
||||
interface EntityBodyInterface extends StreamInterface
|
||||
{
|
||||
/**
|
||||
* Specify a custom callback used to rewind a non-seekable stream. This can be useful entity enclosing requests
|
||||
* that are redirected.
|
||||
*
|
||||
* @param mixed $callable Callable to invoke to rewind a non-seekable stream. The callback must accept an
|
||||
* EntityBodyInterface object, perform the rewind if possible, and return a boolean
|
||||
* representing whether or not the rewind was successful.
|
||||
* @return self
|
||||
*/
|
||||
public function setRewindFunction($callable);
|
||||
|
||||
/**
|
||||
* If the stream is readable, compress the data in the stream using deflate compression. The uncompressed stream is
|
||||
* then closed, and the compressed stream then becomes the wrapped stream.
|
||||
*
|
||||
* @param string $filter Compression filter
|
||||
*
|
||||
* @return bool Returns TRUE on success or FALSE on failure
|
||||
*/
|
||||
public function compress($filter = 'zlib.deflate');
|
||||
|
||||
/**
|
||||
* Decompress a deflated string. Once uncompressed, the uncompressed string is then used as the wrapped stream.
|
||||
*
|
||||
* @param string $filter De-compression filter
|
||||
*
|
||||
* @return bool Returns TRUE on success or FALSE on failure
|
||||
*/
|
||||
public function uncompress($filter = 'zlib.inflate');
|
||||
|
||||
/**
|
||||
* Get the Content-Length of the entity body if possible (alias of getSize)
|
||||
*
|
||||
* @return int|bool Returns the Content-Length or false on failure
|
||||
*/
|
||||
public function getContentLength();
|
||||
|
||||
/**
|
||||
* Guess the Content-Type of a local stream
|
||||
*
|
||||
* @return string|null
|
||||
* @see http://www.php.net/manual/en/function.finfo-open.php
|
||||
*/
|
||||
public function getContentType();
|
||||
|
||||
/**
|
||||
* Get an MD5 checksum of the stream's contents
|
||||
*
|
||||
* @param bool $rawOutput Whether or not to use raw output
|
||||
* @param bool $base64Encode Whether or not to base64 encode raw output (only if raw output is true)
|
||||
*
|
||||
* @return bool|string Returns an MD5 string on success or FALSE on failure
|
||||
*/
|
||||
public function getContentMd5($rawOutput = false, $base64Encode = false);
|
||||
|
||||
/**
|
||||
* Get the Content-Encoding of the EntityBody
|
||||
*
|
||||
* @return bool|string
|
||||
*/
|
||||
public function getContentEncoding();
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http\Exception;
|
||||
|
||||
use Guzzle\Http\Message\RequestInterface;
|
||||
use Guzzle\Http\Message\Response;
|
||||
|
||||
/**
|
||||
* Http request exception thrown when a bad response is received
|
||||
*/
|
||||
class BadResponseException extends RequestException
|
||||
{
|
||||
/** @var Response */
|
||||
private $response;
|
||||
|
||||
/**
|
||||
* Factory method to create a new response exception based on the response code.
|
||||
*
|
||||
* @param RequestInterface $request Request
|
||||
* @param Response $response Response received
|
||||
*
|
||||
* @return BadResponseException
|
||||
*/
|
||||
public static function factory(RequestInterface $request, Response $response)
|
||||
{
|
||||
if ($response->isClientError()) {
|
||||
$label = 'Client error response';
|
||||
$class = __NAMESPACE__ . '\\ClientErrorResponseException';
|
||||
} elseif ($response->isServerError()) {
|
||||
$label = 'Server error response';
|
||||
$class = __NAMESPACE__ . '\\ServerErrorResponseException';
|
||||
} else {
|
||||
$label = 'Unsuccessful response';
|
||||
$class = __CLASS__;
|
||||
$e = new self();
|
||||
}
|
||||
|
||||
$message = $label . PHP_EOL . implode(PHP_EOL, array(
|
||||
'[status code] ' . $response->getStatusCode(),
|
||||
'[reason phrase] ' . $response->getReasonPhrase(),
|
||||
'[url] ' . $request->getUrl(),
|
||||
));
|
||||
|
||||
$e = new $class($message);
|
||||
$e->setResponse($response);
|
||||
$e->setRequest($request);
|
||||
|
||||
return $e;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the response that caused the exception
|
||||
*
|
||||
* @param Response $response Response to set
|
||||
*/
|
||||
public function setResponse(Response $response)
|
||||
{
|
||||
$this->response = $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the response that caused the exception
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function getResponse()
|
||||
{
|
||||
return $this->response;
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http\Exception;
|
||||
|
||||
/**
|
||||
* Exception when a client error is encountered (4xx codes)
|
||||
*/
|
||||
class ClientErrorResponseException extends BadResponseException {}
|
|
@ -1,7 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http\Exception;
|
||||
|
||||
use Guzzle\Common\Exception\RuntimeException;
|
||||
|
||||
class CouldNotRewindStreamException extends RuntimeException implements HttpException {}
|
|
@ -1,101 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http\Exception;
|
||||
|
||||
use Guzzle\Http\Curl\CurlHandle;
|
||||
|
||||
/**
|
||||
* cURL request exception
|
||||
*/
|
||||
class CurlException extends RequestException
|
||||
{
|
||||
private $curlError;
|
||||
private $curlErrorNo;
|
||||
private $handle;
|
||||
private $curlInfo = array();
|
||||
|
||||
/**
|
||||
* Set the cURL error message
|
||||
*
|
||||
* @param string $error Curl error
|
||||
* @param int $number Curl error number
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setError($error, $number)
|
||||
{
|
||||
$this->curlError = $error;
|
||||
$this->curlErrorNo = $number;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the associated curl handle
|
||||
*
|
||||
* @param CurlHandle $handle Curl handle
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setCurlHandle(CurlHandle $handle)
|
||||
{
|
||||
$this->handle = $handle;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the associated cURL handle
|
||||
*
|
||||
* @return CurlHandle|null
|
||||
*/
|
||||
public function getCurlHandle()
|
||||
{
|
||||
return $this->handle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the associated cURL error message
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getError()
|
||||
{
|
||||
return $this->curlError;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the associated cURL error number
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getErrorNo()
|
||||
{
|
||||
return $this->curlErrorNo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns curl information about the transfer
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getCurlInfo()
|
||||
{
|
||||
return $this->curlInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set curl transfer information
|
||||
*
|
||||
* @param array $info Array of curl transfer information
|
||||
*
|
||||
* @return self
|
||||
* @link http://php.net/manual/en/function.curl-getinfo.php
|
||||
*/
|
||||
public function setCurlInfo(array $info)
|
||||
{
|
||||
$this->curlInfo = $info;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http\Exception;
|
||||
|
||||
use Guzzle\Common\Exception\GuzzleException;
|
||||
|
||||
/**
|
||||
* Http exception interface
|
||||
*/
|
||||
interface HttpException extends GuzzleException {}
|
|
@ -1,113 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http\Exception;
|
||||
|
||||
use Guzzle\Common\Exception\ExceptionCollection;
|
||||
use Guzzle\Http\Message\RequestInterface;
|
||||
|
||||
/**
|
||||
* Exception encountered during a multi transfer
|
||||
*/
|
||||
class MultiTransferException extends ExceptionCollection
|
||||
{
|
||||
protected $successfulRequests = array();
|
||||
protected $failedRequests = array();
|
||||
|
||||
/**
|
||||
* Get all of the requests in the transfer
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAllRequests()
|
||||
{
|
||||
return array_merge($this->successfulRequests, $this->failedRequests);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add to the array of successful requests
|
||||
*
|
||||
* @param RequestInterface $request Successful request
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function addSuccessfulRequest(RequestInterface $request)
|
||||
{
|
||||
$this->successfulRequests[] = $request;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add to the array of failed requests
|
||||
*
|
||||
* @param RequestInterface $request Failed request
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function addFailedRequest(RequestInterface $request)
|
||||
{
|
||||
$this->failedRequests[] = $request;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set all of the successful requests
|
||||
*
|
||||
* @param array Array of requests
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setSuccessfulRequests(array $requests)
|
||||
{
|
||||
$this->successfulRequests = $requests;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set all of the failed requests
|
||||
*
|
||||
* @param array Array of requests
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setFailedRequests(array $requests)
|
||||
{
|
||||
$this->failedRequests = $requests;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of successful requests sent in the multi transfer
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getSuccessfulRequests()
|
||||
{
|
||||
return $this->successfulRequests;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of failed requests sent in the multi transfer
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getFailedRequests()
|
||||
{
|
||||
return $this->failedRequests;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the exception object contains a request
|
||||
*
|
||||
* @param RequestInterface $request Request to check
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function containsRequest(RequestInterface $request)
|
||||
{
|
||||
return in_array($request, $this->failedRequests, true) || in_array($request, $this->successfulRequests, true);
|
||||
}
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http\Exception;
|
||||
|
||||
use Guzzle\Common\Exception\RuntimeException;
|
||||
use Guzzle\Http\Message\RequestInterface;
|
||||
|
||||
/**
|
||||
* Http request exception
|
||||
*/
|
||||
class RequestException extends RuntimeException implements HttpException
|
||||
{
|
||||
/** @var RequestInterface */
|
||||
protected $request;
|
||||
|
||||
/**
|
||||
* Set the request that caused the exception
|
||||
*
|
||||
* @param RequestInterface $request Request to set
|
||||
*
|
||||
* @return RequestException
|
||||
*/
|
||||
public function setRequest(RequestInterface $request)
|
||||
{
|
||||
$this->request = $request;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the request that caused the exception
|
||||
*
|
||||
* @return RequestInterface
|
||||
*/
|
||||
public function getRequest()
|
||||
{
|
||||
return $this->request;
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http\Exception;
|
||||
|
||||
/**
|
||||
* Exception when a server error is encountered (5xx codes)
|
||||
*/
|
||||
class ServerErrorResponseException extends BadResponseException {}
|
|
@ -1,5 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http\Exception;
|
||||
|
||||
class TooManyRedirectsException extends BadResponseException {}
|
|
@ -1,83 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http;
|
||||
|
||||
use Guzzle\Common\Event;
|
||||
use Guzzle\Common\HasDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
/**
|
||||
* EntityBody decorator that emits events for read and write methods
|
||||
*/
|
||||
class IoEmittingEntityBody extends AbstractEntityBodyDecorator implements HasDispatcherInterface
|
||||
{
|
||||
/** @var EventDispatcherInterface */
|
||||
protected $eventDispatcher;
|
||||
|
||||
public static function getAllEvents()
|
||||
{
|
||||
return array('body.read', 'body.write');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function setEventDispatcher(EventDispatcherInterface $eventDispatcher)
|
||||
{
|
||||
$this->eventDispatcher = $eventDispatcher;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getEventDispatcher()
|
||||
{
|
||||
if (!$this->eventDispatcher) {
|
||||
$this->eventDispatcher = new EventDispatcher();
|
||||
}
|
||||
|
||||
return $this->eventDispatcher;
|
||||
}
|
||||
|
||||
public function dispatch($eventName, array $context = array())
|
||||
{
|
||||
$this->getEventDispatcher()->dispatch($eventName, new Event($context));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function addSubscriber(EventSubscriberInterface $subscriber)
|
||||
{
|
||||
$this->getEventDispatcher()->addSubscriber($subscriber);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function read($length)
|
||||
{
|
||||
$event = array(
|
||||
'body' => $this,
|
||||
'length' => $length,
|
||||
'read' => $this->body->read($length)
|
||||
);
|
||||
$this->dispatch('body.read', $event);
|
||||
|
||||
return $event['read'];
|
||||
}
|
||||
|
||||
public function write($string)
|
||||
{
|
||||
$event = array(
|
||||
'body' => $this,
|
||||
'write' => $string,
|
||||
'result' => $this->body->write($string)
|
||||
);
|
||||
$this->dispatch('body.write', $event);
|
||||
|
||||
return $event['result'];
|
||||
}
|
||||
}
|
|
@ -1,220 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http\Message;
|
||||
|
||||
use Guzzle\Common\Version;
|
||||
use Guzzle\Common\Collection;
|
||||
use Guzzle\Http\Message\Header\HeaderCollection;
|
||||
use Guzzle\Http\Message\Header\HeaderFactory;
|
||||
use Guzzle\Http\Message\Header\HeaderFactoryInterface;
|
||||
use Guzzle\Http\Message\Header\HeaderInterface;
|
||||
|
||||
/**
|
||||
* Abstract HTTP request/response message
|
||||
*/
|
||||
abstract class AbstractMessage implements MessageInterface
|
||||
{
|
||||
/** @var array HTTP header collection */
|
||||
protected $headers;
|
||||
|
||||
/** @var HeaderFactoryInterface $headerFactory */
|
||||
protected $headerFactory;
|
||||
|
||||
/** @var Collection Custom message parameters that are extendable by plugins */
|
||||
protected $params;
|
||||
|
||||
/** @var string Message protocol */
|
||||
protected $protocol = 'HTTP';
|
||||
|
||||
/** @var string HTTP protocol version of the message */
|
||||
protected $protocolVersion = '1.1';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->params = new Collection();
|
||||
$this->headerFactory = new HeaderFactory();
|
||||
$this->headers = new HeaderCollection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the header factory to use to create headers
|
||||
*
|
||||
* @param HeaderFactoryInterface $factory
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setHeaderFactory(HeaderFactoryInterface $factory)
|
||||
{
|
||||
$this->headerFactory = $factory;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getParams()
|
||||
{
|
||||
return $this->params;
|
||||
}
|
||||
|
||||
public function addHeader($header, $value)
|
||||
{
|
||||
if (isset($this->headers[$header])) {
|
||||
$this->headers[$header]->add($value);
|
||||
} elseif ($value instanceof HeaderInterface) {
|
||||
$this->headers[$header] = $value;
|
||||
} else {
|
||||
$this->headers[$header] = $this->headerFactory->createHeader($header, $value);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function addHeaders(array $headers)
|
||||
{
|
||||
foreach ($headers as $key => $value) {
|
||||
$this->addHeader($key, $value);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getHeader($header)
|
||||
{
|
||||
return $this->headers[$header];
|
||||
}
|
||||
|
||||
public function getHeaders()
|
||||
{
|
||||
return $this->headers;
|
||||
}
|
||||
|
||||
public function getHeaderLines()
|
||||
{
|
||||
$headers = array();
|
||||
foreach ($this->headers as $value) {
|
||||
$headers[] = $value->getName() . ': ' . $value;
|
||||
}
|
||||
|
||||
return $headers;
|
||||
}
|
||||
|
||||
public function setHeader($header, $value)
|
||||
{
|
||||
unset($this->headers[$header]);
|
||||
$this->addHeader($header, $value);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setHeaders(array $headers)
|
||||
{
|
||||
$this->headers->clear();
|
||||
foreach ($headers as $key => $value) {
|
||||
$this->addHeader($key, $value);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function hasHeader($header)
|
||||
{
|
||||
return isset($this->headers[$header]);
|
||||
}
|
||||
|
||||
public function removeHeader($header)
|
||||
{
|
||||
unset($this->headers[$header]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use $message->getHeader()->parseParams()
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function getTokenizedHeader($header, $token = ';')
|
||||
{
|
||||
Version::warn(__METHOD__ . ' is deprecated. Use $message->getHeader()->parseParams()');
|
||||
if ($this->hasHeader($header)) {
|
||||
$data = new Collection();
|
||||
foreach ($this->getHeader($header)->parseParams() as $values) {
|
||||
foreach ($values as $key => $value) {
|
||||
if ($value === '') {
|
||||
$data->set($data->count(), $key);
|
||||
} else {
|
||||
$data->add($key, $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function setTokenizedHeader($header, $data, $token = ';')
|
||||
{
|
||||
Version::warn(__METHOD__ . ' is deprecated.');
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function getCacheControlDirective($directive)
|
||||
{
|
||||
Version::warn(__METHOD__ . ' is deprecated. Use $message->getHeader(\'Cache-Control\')->getDirective()');
|
||||
if (!($header = $this->getHeader('Cache-Control'))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $header->getDirective($directive);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function hasCacheControlDirective($directive)
|
||||
{
|
||||
Version::warn(__METHOD__ . ' is deprecated. Use $message->getHeader(\'Cache-Control\')->hasDirective()');
|
||||
if ($header = $this->getHeader('Cache-Control')) {
|
||||
return $header->hasDirective($directive);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function addCacheControlDirective($directive, $value = true)
|
||||
{
|
||||
Version::warn(__METHOD__ . ' is deprecated. Use $message->getHeader(\'Cache-Control\')->addDirective()');
|
||||
if (!($header = $this->getHeader('Cache-Control'))) {
|
||||
$this->addHeader('Cache-Control', '');
|
||||
$header = $this->getHeader('Cache-Control');
|
||||
}
|
||||
|
||||
$header->addDirective($directive, $value);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function removeCacheControlDirective($directive)
|
||||
{
|
||||
Version::warn(__METHOD__ . ' is deprecated. Use $message->getHeader(\'Cache-Control\')->removeDirective()');
|
||||
if ($header = $this->getHeader('Cache-Control')) {
|
||||
$header->removeDirective($directive);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
|
@ -1,248 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http\Message;
|
||||
|
||||
use Guzzle\Http\EntityBody;
|
||||
use Guzzle\Http\EntityBodyInterface;
|
||||
use Guzzle\Http\QueryString;
|
||||
use Guzzle\Http\RedirectPlugin;
|
||||
use Guzzle\Http\Exception\RequestException;
|
||||
use Guzzle\Http\Mimetypes;
|
||||
|
||||
/**
|
||||
* HTTP request that sends an entity-body in the request message (POST, PUT, PATCH, DELETE)
|
||||
*/
|
||||
class EntityEnclosingRequest extends Request implements EntityEnclosingRequestInterface
|
||||
{
|
||||
/** @var int When the size of the body is greater than 1MB, then send Expect: 100-Continue */
|
||||
protected $expectCutoff = 1048576;
|
||||
|
||||
/** @var EntityBodyInterface $body Body of the request */
|
||||
protected $body;
|
||||
|
||||
/** @var QueryString POST fields to use in the EntityBody */
|
||||
protected $postFields;
|
||||
|
||||
/** @var array POST files to send with the request */
|
||||
protected $postFiles = array();
|
||||
|
||||
public function __construct($method, $url, $headers = array())
|
||||
{
|
||||
$this->postFields = new QueryString();
|
||||
parent::__construct($method, $url, $headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
// Only attempt to include the POST data if it's only fields
|
||||
if (count($this->postFields) && empty($this->postFiles)) {
|
||||
return parent::__toString() . (string) $this->postFields;
|
||||
}
|
||||
|
||||
return parent::__toString() . $this->body;
|
||||
}
|
||||
|
||||
public function setState($state, array $context = array())
|
||||
{
|
||||
parent::setState($state, $context);
|
||||
if ($state == self::STATE_TRANSFER && !$this->body && !count($this->postFields) && !count($this->postFiles)) {
|
||||
$this->setHeader('Content-Length', 0)->removeHeader('Transfer-Encoding');
|
||||
}
|
||||
|
||||
return $this->state;
|
||||
}
|
||||
|
||||
public function setBody($body, $contentType = null)
|
||||
{
|
||||
$this->body = EntityBody::factory($body);
|
||||
|
||||
// Auto detect the Content-Type from the path of the request if possible
|
||||
if ($contentType === null && !$this->hasHeader('Content-Type')) {
|
||||
$contentType = $this->body->getContentType() ?: Mimetypes::getInstance()->fromFilename($this->getPath());
|
||||
}
|
||||
|
||||
if ($contentType) {
|
||||
$this->setHeader('Content-Type', $contentType);
|
||||
}
|
||||
|
||||
// Always add the Expect 100-Continue header if the body cannot be rewound. This helps with redirects.
|
||||
if (!$this->body->isSeekable() && $this->expectCutoff !== false) {
|
||||
$this->setHeader('Expect', '100-Continue');
|
||||
}
|
||||
|
||||
// Set the Content-Length header if it can be determined
|
||||
$size = $this->body->getContentLength();
|
||||
if ($size !== null && $size !== false) {
|
||||
$this->setHeader('Content-Length', $size);
|
||||
if ($size > $this->expectCutoff) {
|
||||
$this->setHeader('Expect', '100-Continue');
|
||||
}
|
||||
} elseif (!$this->hasHeader('Content-Length')) {
|
||||
if ('1.1' == $this->protocolVersion) {
|
||||
$this->setHeader('Transfer-Encoding', 'chunked');
|
||||
} else {
|
||||
throw new RequestException(
|
||||
'Cannot determine Content-Length and cannot use chunked Transfer-Encoding when using HTTP/1.0'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getBody()
|
||||
{
|
||||
return $this->body;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the size that the entity body of the request must exceed before adding the Expect: 100-Continue header.
|
||||
*
|
||||
* @param int|bool $size Cutoff in bytes. Set to false to never send the expect header (even with non-seekable data)
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setExpectHeaderCutoff($size)
|
||||
{
|
||||
$this->expectCutoff = $size;
|
||||
if ($size === false || !$this->body) {
|
||||
$this->removeHeader('Expect');
|
||||
} elseif ($this->body && $this->body->getSize() && $this->body->getSize() > $size) {
|
||||
$this->setHeader('Expect', '100-Continue');
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function configureRedirects($strict = false, $maxRedirects = 5)
|
||||
{
|
||||
$this->getParams()->set(RedirectPlugin::STRICT_REDIRECTS, $strict);
|
||||
if ($maxRedirects == 0) {
|
||||
$this->getParams()->set(RedirectPlugin::DISABLE, true);
|
||||
} else {
|
||||
$this->getParams()->set(RedirectPlugin::MAX_REDIRECTS, $maxRedirects);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPostField($field)
|
||||
{
|
||||
return $this->postFields->get($field);
|
||||
}
|
||||
|
||||
public function getPostFields()
|
||||
{
|
||||
return $this->postFields;
|
||||
}
|
||||
|
||||
public function setPostField($key, $value)
|
||||
{
|
||||
$this->postFields->set($key, $value);
|
||||
$this->processPostFields();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function addPostFields($fields)
|
||||
{
|
||||
$this->postFields->merge($fields);
|
||||
$this->processPostFields();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removePostField($field)
|
||||
{
|
||||
$this->postFields->remove($field);
|
||||
$this->processPostFields();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPostFiles()
|
||||
{
|
||||
return $this->postFiles;
|
||||
}
|
||||
|
||||
public function getPostFile($fieldName)
|
||||
{
|
||||
return isset($this->postFiles[$fieldName]) ? $this->postFiles[$fieldName] : null;
|
||||
}
|
||||
|
||||
public function removePostFile($fieldName)
|
||||
{
|
||||
unset($this->postFiles[$fieldName]);
|
||||
$this->processPostFields();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function addPostFile($field, $filename = null, $contentType = null)
|
||||
{
|
||||
$data = null;
|
||||
|
||||
if ($field instanceof PostFileInterface) {
|
||||
$data = $field;
|
||||
} elseif (is_array($filename)) {
|
||||
// Allow multiple values to be set in a single key
|
||||
foreach ($filename as $file) {
|
||||
$this->addPostFile($field, $file, $contentType);
|
||||
}
|
||||
return $this;
|
||||
} elseif (!is_string($filename)) {
|
||||
throw new RequestException('The path to a file must be a string');
|
||||
} elseif (!empty($filename)) {
|
||||
// Adding an empty file will cause cURL to error out
|
||||
$data = new PostFile($field, $filename, $contentType);
|
||||
}
|
||||
|
||||
if ($data) {
|
||||
if (!isset($this->postFiles[$data->getFieldName()])) {
|
||||
$this->postFiles[$data->getFieldName()] = array($data);
|
||||
} else {
|
||||
$this->postFiles[$data->getFieldName()][] = $data;
|
||||
}
|
||||
$this->processPostFields();
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function addPostFiles(array $files)
|
||||
{
|
||||
foreach ($files as $key => $file) {
|
||||
if ($file instanceof PostFileInterface) {
|
||||
$this->addPostFile($file, null, null, false);
|
||||
} elseif (is_string($file)) {
|
||||
// Convert non-associative array keys into 'file'
|
||||
if (is_numeric($key)) {
|
||||
$key = 'file';
|
||||
}
|
||||
$this->addPostFile($key, $file, null, false);
|
||||
} else {
|
||||
throw new RequestException('File must be a string or instance of PostFileInterface');
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine what type of request should be sent based on post fields
|
||||
*/
|
||||
protected function processPostFields()
|
||||
{
|
||||
if (!$this->postFiles) {
|
||||
$this->removeHeader('Expect')->setHeader('Content-Type', self::URL_ENCODED);
|
||||
} else {
|
||||
$this->setHeader('Content-Type', self::MULTIPART);
|
||||
if ($this->expectCutoff !== false) {
|
||||
$this->setHeader('Expect', '100-Continue');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,136 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http\Message;
|
||||
|
||||
use Guzzle\Http\Exception\RequestException;
|
||||
use Guzzle\Http\EntityBodyInterface;
|
||||
use Guzzle\Http\QueryString;
|
||||
|
||||
/**
|
||||
* HTTP request that sends an entity-body in the request message (POST, PUT)
|
||||
*/
|
||||
interface EntityEnclosingRequestInterface extends RequestInterface
|
||||
{
|
||||
const URL_ENCODED = 'application/x-www-form-urlencoded; charset=utf-8';
|
||||
const MULTIPART = 'multipart/form-data';
|
||||
|
||||
/**
|
||||
* Set the body of the request
|
||||
*
|
||||
* @param string|resource|EntityBodyInterface $body Body to use in the entity body of the request
|
||||
* @param string $contentType Content-Type to set. Leave null to use an existing
|
||||
* Content-Type or to guess the Content-Type
|
||||
* @return self
|
||||
* @throws RequestException if the protocol is < 1.1 and Content-Length can not be determined
|
||||
*/
|
||||
public function setBody($body, $contentType = null);
|
||||
|
||||
/**
|
||||
* Get the body of the request if set
|
||||
*
|
||||
* @return EntityBodyInterface|null
|
||||
*/
|
||||
public function getBody();
|
||||
|
||||
/**
|
||||
* Get a POST field from the request
|
||||
*
|
||||
* @param string $field Field to retrieve
|
||||
*
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function getPostField($field);
|
||||
|
||||
/**
|
||||
* Get the post fields that will be used in the request
|
||||
*
|
||||
* @return QueryString
|
||||
*/
|
||||
public function getPostFields();
|
||||
|
||||
/**
|
||||
* Set a POST field value
|
||||
*
|
||||
* @param string $key Key to set
|
||||
* @param string $value Value to set
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setPostField($key, $value);
|
||||
|
||||
/**
|
||||
* Add POST fields to use in the request
|
||||
*
|
||||
* @param QueryString|array $fields POST fields
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function addPostFields($fields);
|
||||
|
||||
/**
|
||||
* Remove a POST field or file by name
|
||||
*
|
||||
* @param string $field Name of the POST field or file to remove
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function removePostField($field);
|
||||
|
||||
/**
|
||||
* Returns an associative array of POST field names to PostFileInterface objects
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getPostFiles();
|
||||
|
||||
/**
|
||||
* Get a POST file from the request
|
||||
*
|
||||
* @param string $fieldName POST fields to retrieve
|
||||
*
|
||||
* @return array|null Returns an array wrapping an array of PostFileInterface objects
|
||||
*/
|
||||
public function getPostFile($fieldName);
|
||||
|
||||
/**
|
||||
* Remove a POST file from the request
|
||||
*
|
||||
* @param string $fieldName POST file field name to remove
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function removePostFile($fieldName);
|
||||
|
||||
/**
|
||||
* Add a POST file to the upload
|
||||
*
|
||||
* @param string $field POST field to use (e.g. file). Used to reference content from the server.
|
||||
* @param string $filename Full path to the file. Do not include the @ symbol.
|
||||
* @param string $contentType Optional Content-Type to add to the Content-Disposition.
|
||||
* Default behavior is to guess. Set to false to not specify.
|
||||
* @return self
|
||||
*/
|
||||
public function addPostFile($field, $filename = null, $contentType = null);
|
||||
|
||||
/**
|
||||
* Add POST files to use in the upload
|
||||
*
|
||||
* @param array $files An array of POST fields => filenames where filename can be a string or PostFileInterface
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function addPostFiles(array $files);
|
||||
|
||||
/**
|
||||
* Configure how redirects are handled for the request
|
||||
*
|
||||
* @param bool $strict Set to true to follow strict RFC compliance when redirecting POST requests. Most
|
||||
* browsers with follow a 301-302 redirect for a POST request with a GET request. This is
|
||||
* the default behavior of Guzzle. Enable strict redirects to redirect these responses
|
||||
* with a POST rather than a GET request.
|
||||
* @param int $maxRedirects Specify the maximum number of allowed redirects. Set to 0 to disable redirects.
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function configureRedirects($strict = false, $maxRedirects = 5);
|
||||
}
|
|
@ -1,177 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http\Message;
|
||||
|
||||
use Guzzle\Common\Version;
|
||||
use Guzzle\Http\Message\Header\HeaderInterface;
|
||||
|
||||
/**
|
||||
* Represents a header and all of the values stored by that header
|
||||
*/
|
||||
class Header implements HeaderInterface
|
||||
{
|
||||
protected $values = array();
|
||||
protected $header;
|
||||
protected $glue;
|
||||
|
||||
/**
|
||||
* @param string $header Name of the header
|
||||
* @param array|string $values Values of the header as an array or a scalar
|
||||
* @param string $glue Glue used to combine multiple values into a string
|
||||
*/
|
||||
public function __construct($header, $values = array(), $glue = ',')
|
||||
{
|
||||
$this->header = trim($header);
|
||||
$this->glue = $glue;
|
||||
|
||||
foreach ((array) $values as $value) {
|
||||
foreach ((array) $value as $v) {
|
||||
$this->values[] = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return implode($this->glue . ' ', $this->toArray());
|
||||
}
|
||||
|
||||
public function add($value)
|
||||
{
|
||||
$this->values[] = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return $this->header;
|
||||
}
|
||||
|
||||
public function setName($name)
|
||||
{
|
||||
$this->header = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setGlue($glue)
|
||||
{
|
||||
$this->glue = $glue;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getGlue()
|
||||
{
|
||||
return $this->glue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize the header to be a single header with an array of values.
|
||||
*
|
||||
* If any values of the header contains the glue string value (e.g. ","), then the value will be exploded into
|
||||
* multiple entries in the header.
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function normalize()
|
||||
{
|
||||
$values = $this->toArray();
|
||||
|
||||
for ($i = 0, $total = count($values); $i < $total; $i++) {
|
||||
if (strpos($values[$i], $this->glue) !== false) {
|
||||
foreach (explode($this->glue, $values[$i]) as $v) {
|
||||
$values[] = trim($v);
|
||||
}
|
||||
unset($values[$i]);
|
||||
}
|
||||
}
|
||||
|
||||
$this->values = array_values($values);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function hasValue($searchValue)
|
||||
{
|
||||
return in_array($searchValue, $this->toArray());
|
||||
}
|
||||
|
||||
public function removeValue($searchValue)
|
||||
{
|
||||
$this->values = array_values(array_filter($this->values, function ($value) use ($searchValue) {
|
||||
return $value != $searchValue;
|
||||
}));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function toArray()
|
||||
{
|
||||
return $this->values;
|
||||
}
|
||||
|
||||
public function count()
|
||||
{
|
||||
return count($this->toArray());
|
||||
}
|
||||
|
||||
public function getIterator()
|
||||
{
|
||||
return new \ArrayIterator($this->toArray());
|
||||
}
|
||||
|
||||
public function parseParams()
|
||||
{
|
||||
$params = $matches = array();
|
||||
$callback = array($this, 'trimHeader');
|
||||
|
||||
// Normalize the header into a single array and iterate over all values
|
||||
foreach ($this->normalize()->toArray() as $val) {
|
||||
$part = array();
|
||||
foreach (preg_split('/;(?=([^"]*"[^"]*")*[^"]*$)/', $val) as $kvp) {
|
||||
preg_match_all('/<[^>]+>|[^=]+/', $kvp, $matches);
|
||||
$pieces = array_map($callback, $matches[0]);
|
||||
$part[$pieces[0]] = isset($pieces[1]) ? $pieces[1] : '';
|
||||
}
|
||||
$params[] = $part;
|
||||
}
|
||||
|
||||
return $params;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function hasExactHeader($header)
|
||||
{
|
||||
Version::warn(__METHOD__ . ' is deprecated');
|
||||
return $this->header == $header;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function raw()
|
||||
{
|
||||
Version::warn(__METHOD__ . ' is deprecated. Use toArray()');
|
||||
return $this->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Trim a header by removing excess spaces and wrapping quotes
|
||||
*
|
||||
* @param $str
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function trimHeader($str)
|
||||
{
|
||||
static $trimmed = "\"' \n\t";
|
||||
|
||||
return trim($str, $trimmed);
|
||||
}
|
||||
}
|
|
@ -1,121 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http\Message\Header;
|
||||
|
||||
use Guzzle\Http\Message\Header;
|
||||
|
||||
/**
|
||||
* Provides helpful functionality for Cache-Control headers
|
||||
*/
|
||||
class CacheControl extends Header
|
||||
{
|
||||
/** @var array */
|
||||
protected $directives;
|
||||
|
||||
public function add($value)
|
||||
{
|
||||
parent::add($value);
|
||||
$this->directives = null;
|
||||
}
|
||||
|
||||
public function removeValue($searchValue)
|
||||
{
|
||||
parent::removeValue($searchValue);
|
||||
$this->directives = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a specific cache control directive exists
|
||||
*
|
||||
* @param string $param Directive to retrieve
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasDirective($param)
|
||||
{
|
||||
$directives = $this->getDirectives();
|
||||
|
||||
return isset($directives[$param]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a specific cache control directive
|
||||
*
|
||||
* @param string $param Directive to retrieve
|
||||
*
|
||||
* @return string|bool|null
|
||||
*/
|
||||
public function getDirective($param)
|
||||
{
|
||||
$directives = $this->getDirectives();
|
||||
|
||||
return isset($directives[$param]) ? $directives[$param] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a cache control directive
|
||||
*
|
||||
* @param string $param Directive to add
|
||||
* @param string $value Value to set
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function addDirective($param, $value)
|
||||
{
|
||||
$directives = $this->getDirectives();
|
||||
$directives[$param] = $value;
|
||||
$this->updateFromDirectives($directives);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a cache control directive by name
|
||||
*
|
||||
* @param string $param Directive to remove
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function removeDirective($param)
|
||||
{
|
||||
$directives = $this->getDirectives();
|
||||
unset($directives[$param]);
|
||||
$this->updateFromDirectives($directives);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an associative array of cache control directives
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getDirectives()
|
||||
{
|
||||
if ($this->directives === null) {
|
||||
$this->directives = array();
|
||||
foreach ($this->parseParams() as $collection) {
|
||||
foreach ($collection as $key => $value) {
|
||||
$this->directives[$key] = $value === '' ? true : $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->directives;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the header value based on the parsed directives
|
||||
*
|
||||
* @param array $directives Array of cache control directives
|
||||
*/
|
||||
protected function updateFromDirectives(array $directives)
|
||||
{
|
||||
$this->directives = $directives;
|
||||
$this->values = array();
|
||||
|
||||
foreach ($directives as $key => $value) {
|
||||
$this->values[] = $value === true ? $key : "{$key}={$value}";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,109 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http\Message\Header;
|
||||
|
||||
use Guzzle\Common\Collection;
|
||||
use Guzzle\Common\ToArrayInterface;
|
||||
|
||||
/**
|
||||
* Provides a case-insensitive collection of headers
|
||||
*/
|
||||
class HeaderCollection implements \IteratorAggregate, \Countable, \ArrayAccess, ToArrayInterface
|
||||
{
|
||||
/** @var array */
|
||||
protected $headers;
|
||||
|
||||
public function __construct($headers = array())
|
||||
{
|
||||
$this->headers = $headers;
|
||||
}
|
||||
|
||||
public function __clone()
|
||||
{
|
||||
foreach ($this->headers as &$header) {
|
||||
$header = clone $header;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the header collection
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
$this->headers = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a header on the collection
|
||||
*
|
||||
* @param HeaderInterface $header Header to add
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function add(HeaderInterface $header)
|
||||
{
|
||||
$this->headers[strtolower($header->getName())] = $header;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of header objects
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAll()
|
||||
{
|
||||
return $this->headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias of offsetGet
|
||||
*/
|
||||
public function get($key)
|
||||
{
|
||||
return $this->offsetGet($key);
|
||||
}
|
||||
|
||||
public function count()
|
||||
{
|
||||
return count($this->headers);
|
||||
}
|
||||
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
return isset($this->headers[strtolower($offset)]);
|
||||
}
|
||||
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
$l = strtolower($offset);
|
||||
|
||||
return isset($this->headers[$l]) ? $this->headers[$l] : null;
|
||||
}
|
||||
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
$this->add($value);
|
||||
}
|
||||
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
unset($this->headers[strtolower($offset)]);
|
||||
}
|
||||
|
||||
public function getIterator()
|
||||
{
|
||||
return new \ArrayIterator($this->headers);
|
||||
}
|
||||
|
||||
public function toArray()
|
||||
{
|
||||
$result = array();
|
||||
foreach ($this->headers as $header) {
|
||||
$result[$header->getName()] = $header->toArray();
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http\Message\Header;
|
||||
|
||||
use Guzzle\Http\Message\Header;
|
||||
|
||||
/**
|
||||
* Default header factory implementation
|
||||
*/
|
||||
class HeaderFactory implements HeaderFactoryInterface
|
||||
{
|
||||
/** @var array */
|
||||
protected $mapping = array(
|
||||
'cache-control' => 'Guzzle\Http\Message\Header\CacheControl',
|
||||
'link' => 'Guzzle\Http\Message\Header\Link',
|
||||
);
|
||||
|
||||
public function createHeader($header, $value = null)
|
||||
{
|
||||
$lowercase = strtolower($header);
|
||||
|
||||
return isset($this->mapping[$lowercase])
|
||||
? new $this->mapping[$lowercase]($header, $value)
|
||||
: new Header($header, $value);
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http\Message\Header;
|
||||
|
||||
/**
|
||||
* Interface for creating headers
|
||||
*/
|
||||
interface HeaderFactoryInterface
|
||||
{
|
||||
/**
|
||||
* Create a header from a header name and a single value
|
||||
*
|
||||
* @param string $header Name of the header to create
|
||||
* @param string $value Value to set on the header
|
||||
*
|
||||
* @return HeaderInterface
|
||||
*/
|
||||
public function createHeader($header, $value = null);
|
||||
}
|
|
@ -1,83 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http\Message\Header;
|
||||
|
||||
use Guzzle\Common\ToArrayInterface;
|
||||
|
||||
interface HeaderInterface extends ToArrayInterface, \Countable, \IteratorAggregate
|
||||
{
|
||||
/**
|
||||
* Convert the header to a string
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString();
|
||||
|
||||
/**
|
||||
* Add a value to the list of header values
|
||||
*
|
||||
* @param string $value Value to add to the header
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function add($value);
|
||||
|
||||
/**
|
||||
* Get the name of the header
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName();
|
||||
|
||||
/**
|
||||
* Change the name of the header
|
||||
*
|
||||
* @param string $name Name to change to
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setName($name);
|
||||
|
||||
/**
|
||||
* Change the glue used to implode the values
|
||||
*
|
||||
* @param string $glue Glue used to implode multiple values
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setGlue($glue);
|
||||
|
||||
/**
|
||||
* Get the glue used to implode multiple values into a string
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getGlue();
|
||||
|
||||
/**
|
||||
* Check if the collection of headers has a particular value
|
||||
*
|
||||
* @param string $searchValue Value to search for
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasValue($searchValue);
|
||||
|
||||
/**
|
||||
* Remove a specific value from the header
|
||||
*
|
||||
* @param string $searchValue Value to remove
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function removeValue($searchValue);
|
||||
|
||||
/**
|
||||
* Parse a header containing ";" separated data into an array of associative arrays representing the header
|
||||
* key value pair data of the header. When a parameter does not contain a value, but just contains a key, this
|
||||
* function will inject a key with a '' string value.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function parseParams();
|
||||
}
|
|
@ -1,93 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http\Message\Header;
|
||||
|
||||
use Guzzle\Http\Message\Header;
|
||||
|
||||
/**
|
||||
* Provides helpful functionality for link headers
|
||||
*/
|
||||
class Link extends Header
|
||||
{
|
||||
/**
|
||||
* Add a link to the header
|
||||
*
|
||||
* @param string $url Link URL
|
||||
* @param string $rel Link rel
|
||||
* @param array $params Other link parameters
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function addLink($url, $rel, array $params = array())
|
||||
{
|
||||
$values = array("<{$url}>", "rel=\"{$rel}\"");
|
||||
|
||||
foreach ($params as $k => $v) {
|
||||
$values[] = "{$k}=\"{$v}\"";
|
||||
}
|
||||
|
||||
return $this->add(implode('; ', $values));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a specific link exists for a given rel attribute
|
||||
*
|
||||
* @param string $rel rel value
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasLink($rel)
|
||||
{
|
||||
return $this->getLink($rel) !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a specific link for a given rel attribute
|
||||
*
|
||||
* @param string $rel Rel value
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
public function getLink($rel)
|
||||
{
|
||||
foreach ($this->getLinks() as $link) {
|
||||
if (isset($link['rel']) && $link['rel'] == $rel) {
|
||||
return $link;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an associative array of links
|
||||
*
|
||||
* For example:
|
||||
* Link: <http:/.../front.jpeg>; rel=front; type="image/jpeg", <http://.../back.jpeg>; rel=back; type="image/jpeg"
|
||||
*
|
||||
* <code>
|
||||
* var_export($response->getLinks());
|
||||
* array(
|
||||
* array(
|
||||
* 'url' => 'http:/.../front.jpeg',
|
||||
* 'rel' => 'back',
|
||||
* 'type' => 'image/jpeg',
|
||||
* )
|
||||
* )
|
||||
* </code>
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getLinks()
|
||||
{
|
||||
$links = $this->parseParams();
|
||||
|
||||
foreach ($links as &$link) {
|
||||
$key = key($link);
|
||||
unset($link[$key]);
|
||||
$link['url'] = trim($key, '<> ');
|
||||
}
|
||||
|
||||
return $links;
|
||||
}
|
||||
}
|
|
@ -1,102 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http\Message;
|
||||
|
||||
/**
|
||||
* Request and response message interface
|
||||
*/
|
||||
interface MessageInterface
|
||||
{
|
||||
/**
|
||||
* Get application and plugin specific parameters set on the message.
|
||||
*
|
||||
* @return \Guzzle\Common\Collection
|
||||
*/
|
||||
public function getParams();
|
||||
|
||||
/**
|
||||
* Add a header to an existing collection of headers.
|
||||
*
|
||||
* @param string $header Header name to add
|
||||
* @param string $value Value of the header
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function addHeader($header, $value);
|
||||
|
||||
/**
|
||||
* Add and merge in an array of HTTP headers.
|
||||
*
|
||||
* @param array $headers Associative array of header data.
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function addHeaders(array $headers);
|
||||
|
||||
/**
|
||||
* Retrieve an HTTP header by name. Performs a case-insensitive search of all headers.
|
||||
*
|
||||
* @param string $header Header to retrieve.
|
||||
*
|
||||
* @return Header|null
|
||||
*/
|
||||
public function getHeader($header);
|
||||
|
||||
/**
|
||||
* Get all headers as a collection
|
||||
*
|
||||
* @return \Guzzle\Http\Message\Header\HeaderCollection
|
||||
*/
|
||||
public function getHeaders();
|
||||
|
||||
/**
|
||||
* Check if the specified header is present.
|
||||
*
|
||||
* @param string $header The header to check.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasHeader($header);
|
||||
|
||||
/**
|
||||
* Remove a specific HTTP header.
|
||||
*
|
||||
* @param string $header HTTP header to remove.
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function removeHeader($header);
|
||||
|
||||
/**
|
||||
* Set an HTTP header and overwrite any existing value for the header
|
||||
*
|
||||
* @param string $header Name of the header to set.
|
||||
* @param mixed $value Value to set.
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setHeader($header, $value);
|
||||
|
||||
/**
|
||||
* Overwrite all HTTP headers with the supplied array of headers
|
||||
*
|
||||
* @param array $headers Associative array of header data.
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setHeaders(array $headers);
|
||||
|
||||
/**
|
||||
* Get an array of message header lines (e.g. ["Host: example.com", ...])
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getHeaderLines();
|
||||
|
||||
/**
|
||||
* Get the raw message headers as a string
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRawHeaders();
|
||||
}
|
|
@ -1,109 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http\Message;
|
||||
|
||||
use Guzzle\Common\Version;
|
||||
use Guzzle\Common\Exception\InvalidArgumentException;
|
||||
use Guzzle\Http\Mimetypes;
|
||||
|
||||
/**
|
||||
* POST file upload
|
||||
*/
|
||||
class PostFile implements PostFileInterface
|
||||
{
|
||||
protected $fieldName;
|
||||
protected $contentType;
|
||||
protected $filename;
|
||||
|
||||
/**
|
||||
* @param string $fieldName Name of the field
|
||||
* @param string $filename Path to the file
|
||||
* @param string $contentType Content-Type of the upload
|
||||
*/
|
||||
public function __construct($fieldName, $filename, $contentType = null)
|
||||
{
|
||||
$this->fieldName = $fieldName;
|
||||
$this->setFilename($filename);
|
||||
$this->contentType = $contentType ?: $this->guessContentType();
|
||||
}
|
||||
|
||||
public function setFieldName($name)
|
||||
{
|
||||
$this->fieldName = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getFieldName()
|
||||
{
|
||||
return $this->fieldName;
|
||||
}
|
||||
|
||||
public function setFilename($filename)
|
||||
{
|
||||
// Remove leading @ symbol
|
||||
if (strpos($filename, '@') === 0) {
|
||||
$filename = substr($filename, 1);
|
||||
}
|
||||
|
||||
if (!is_readable($filename)) {
|
||||
throw new InvalidArgumentException("Unable to open {$filename} for reading");
|
||||
}
|
||||
|
||||
$this->filename = $filename;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getFilename()
|
||||
{
|
||||
return $this->filename;
|
||||
}
|
||||
|
||||
public function setContentType($type)
|
||||
{
|
||||
$this->contentType = $type;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getContentType()
|
||||
{
|
||||
return $this->contentType;
|
||||
}
|
||||
|
||||
public function getCurlValue()
|
||||
{
|
||||
// PHP 5.5 introduced a CurlFile object that deprecates the old @filename syntax
|
||||
// See: https://wiki.php.net/rfc/curl-file-upload
|
||||
if (function_exists('curl_file_create')) {
|
||||
return curl_file_create($this->filename, $this->contentType, basename($this->filename));
|
||||
}
|
||||
|
||||
// Use the old style if using an older version of PHP
|
||||
$value = "@{$this->filename};filename=" . basename($this->filename);
|
||||
if ($this->contentType) {
|
||||
$value .= ';type=' . $this->contentType;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function getCurlString()
|
||||
{
|
||||
Version::warn(__METHOD__ . ' is deprecated. Use getCurlValue()');
|
||||
return $this->getCurlValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the Content-Type of the file
|
||||
*/
|
||||
protected function guessContentType()
|
||||
{
|
||||
return Mimetypes::getInstance()->fromFilename($this->filename) ?: 'application/octet-stream';
|
||||
}
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http\Message;
|
||||
|
||||
use Guzzle\Common\Exception\InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* POST file upload
|
||||
*/
|
||||
interface PostFileInterface
|
||||
{
|
||||
/**
|
||||
* Set the name of the field
|
||||
*
|
||||
* @param string $name Field name
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setFieldName($name);
|
||||
|
||||
/**
|
||||
* Get the name of the field
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFieldName();
|
||||
|
||||
/**
|
||||
* Set the path to the file
|
||||
*
|
||||
* @param string $path Full path to the file
|
||||
*
|
||||
* @return self
|
||||
* @throws InvalidArgumentException if the file cannot be read
|
||||
*/
|
||||
public function setFilename($path);
|
||||
|
||||
/**
|
||||
* Get the full path to the file
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFilename();
|
||||
|
||||
/**
|
||||
* Set the Content-Type of the file
|
||||
*
|
||||
* @param string $type Content type
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setContentType($type);
|
||||
|
||||
/**
|
||||
* Get the Content-Type of the file
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getContentType();
|
||||
|
||||
/**
|
||||
* Get a cURL ready string or CurlFile object for the upload
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCurlValue();
|
||||
}
|
|
@ -1,637 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http\Message;
|
||||
|
||||
use Guzzle\Common\Version;
|
||||
use Guzzle\Common\Event;
|
||||
use Guzzle\Common\Collection;
|
||||
use Guzzle\Common\Exception\RuntimeException;
|
||||
use Guzzle\Common\Exception\InvalidArgumentException;
|
||||
use Guzzle\Http\Exception\RequestException;
|
||||
use Guzzle\Http\Exception\BadResponseException;
|
||||
use Guzzle\Http\ClientInterface;
|
||||
use Guzzle\Http\EntityBody;
|
||||
use Guzzle\Http\EntityBodyInterface;
|
||||
use Guzzle\Http\Message\Header\HeaderInterface;
|
||||
use Guzzle\Http\Url;
|
||||
use Guzzle\Parser\ParserRegistry;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
/**
|
||||
* HTTP request class to send requests
|
||||
*/
|
||||
class Request extends AbstractMessage implements RequestInterface
|
||||
{
|
||||
/** @var EventDispatcherInterface */
|
||||
protected $eventDispatcher;
|
||||
|
||||
/** @var Url HTTP Url */
|
||||
protected $url;
|
||||
|
||||
/** @var string HTTP method (GET, PUT, POST, DELETE, HEAD, OPTIONS, TRACE) */
|
||||
protected $method;
|
||||
|
||||
/** @var ClientInterface */
|
||||
protected $client;
|
||||
|
||||
/** @var Response Response of the request */
|
||||
protected $response;
|
||||
|
||||
/** @var EntityBodyInterface Response body */
|
||||
protected $responseBody;
|
||||
|
||||
/** @var string State of the request object */
|
||||
protected $state;
|
||||
|
||||
/** @var string Authentication username */
|
||||
protected $username;
|
||||
|
||||
/** @var string Auth password */
|
||||
protected $password;
|
||||
|
||||
/** @var Collection cURL specific transfer options */
|
||||
protected $curlOptions;
|
||||
|
||||
/** @var bool */
|
||||
protected $isRedirect = false;
|
||||
|
||||
public static function getAllEvents()
|
||||
{
|
||||
return array(
|
||||
// Called when receiving or uploading data through cURL
|
||||
'curl.callback.read', 'curl.callback.write', 'curl.callback.progress',
|
||||
// Cloning a request
|
||||
'request.clone',
|
||||
// About to send the request, sent request, completed transaction
|
||||
'request.before_send', 'request.sent', 'request.complete',
|
||||
// A request received a successful response
|
||||
'request.success',
|
||||
// A request received an unsuccessful response
|
||||
'request.error',
|
||||
// An exception is being thrown because of an unsuccessful response
|
||||
'request.exception',
|
||||
// Received response status line
|
||||
'request.receive.status_line'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $method HTTP method
|
||||
* @param string|Url $url HTTP URL to connect to. The URI scheme, host header, and URI are parsed from the
|
||||
* full URL. If query string parameters are present they will be parsed as well.
|
||||
* @param array|Collection $headers HTTP headers
|
||||
*/
|
||||
public function __construct($method, $url, $headers = array())
|
||||
{
|
||||
parent::__construct();
|
||||
$this->method = strtoupper($method);
|
||||
$this->curlOptions = new Collection();
|
||||
$this->setUrl($url);
|
||||
|
||||
if ($headers) {
|
||||
// Special handling for multi-value headers
|
||||
foreach ($headers as $key => $value) {
|
||||
// Deal with collisions with Host and Authorization
|
||||
if ($key == 'host' || $key == 'Host') {
|
||||
$this->setHeader($key, $value);
|
||||
} elseif ($value instanceof HeaderInterface) {
|
||||
$this->addHeader($key, $value);
|
||||
} else {
|
||||
foreach ((array) $value as $v) {
|
||||
$this->addHeader($key, $v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->setState(self::STATE_NEW);
|
||||
}
|
||||
|
||||
public function __clone()
|
||||
{
|
||||
if ($this->eventDispatcher) {
|
||||
$this->eventDispatcher = clone $this->eventDispatcher;
|
||||
}
|
||||
$this->curlOptions = clone $this->curlOptions;
|
||||
$this->params = clone $this->params;
|
||||
$this->url = clone $this->url;
|
||||
$this->response = $this->responseBody = null;
|
||||
$this->headers = clone $this->headers;
|
||||
|
||||
$this->setState(RequestInterface::STATE_NEW);
|
||||
$this->dispatch('request.clone', array('request' => $this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the HTTP request as a string
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->getRawHeaders() . "\r\n\r\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Default method that will throw exceptions if an unsuccessful response is received.
|
||||
*
|
||||
* @param Event $event Received
|
||||
* @throws BadResponseException if the response is not successful
|
||||
*/
|
||||
public static function onRequestError(Event $event)
|
||||
{
|
||||
$e = BadResponseException::factory($event['request'], $event['response']);
|
||||
$event['request']->setState(self::STATE_ERROR, array('exception' => $e) + $event->toArray());
|
||||
throw $e;
|
||||
}
|
||||
|
||||
public function setClient(ClientInterface $client)
|
||||
{
|
||||
$this->client = $client;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getClient()
|
||||
{
|
||||
return $this->client;
|
||||
}
|
||||
|
||||
public function getRawHeaders()
|
||||
{
|
||||
$protocolVersion = $this->protocolVersion ?: '1.1';
|
||||
|
||||
return trim($this->method . ' ' . $this->getResource()) . ' '
|
||||
. strtoupper(str_replace('https', 'http', $this->url->getScheme()))
|
||||
. '/' . $protocolVersion . "\r\n" . implode("\r\n", $this->getHeaderLines());
|
||||
}
|
||||
|
||||
public function setUrl($url)
|
||||
{
|
||||
if ($url instanceof Url) {
|
||||
$this->url = $url;
|
||||
} else {
|
||||
$this->url = Url::factory($url);
|
||||
}
|
||||
|
||||
// Update the port and host header
|
||||
$this->setPort($this->url->getPort());
|
||||
|
||||
if ($this->url->getUsername() || $this->url->getPassword()) {
|
||||
$this->setAuth($this->url->getUsername(), $this->url->getPassword());
|
||||
// Remove the auth info from the URL
|
||||
$this->url->setUsername(null);
|
||||
$this->url->setPassword(null);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function send()
|
||||
{
|
||||
if (!$this->client) {
|
||||
throw new RuntimeException('A client must be set on the request');
|
||||
}
|
||||
|
||||
return $this->client->send($this);
|
||||
}
|
||||
|
||||
public function getResponse()
|
||||
{
|
||||
return $this->response;
|
||||
}
|
||||
|
||||
public function getQuery($asString = false)
|
||||
{
|
||||
return $asString
|
||||
? (string) $this->url->getQuery()
|
||||
: $this->url->getQuery();
|
||||
}
|
||||
|
||||
public function getMethod()
|
||||
{
|
||||
return $this->method;
|
||||
}
|
||||
|
||||
public function getScheme()
|
||||
{
|
||||
return $this->url->getScheme();
|
||||
}
|
||||
|
||||
public function setScheme($scheme)
|
||||
{
|
||||
$this->url->setScheme($scheme);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getHost()
|
||||
{
|
||||
return $this->url->getHost();
|
||||
}
|
||||
|
||||
public function setHost($host)
|
||||
{
|
||||
$this->url->setHost($host);
|
||||
$this->setPort($this->url->getPort());
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getProtocolVersion()
|
||||
{
|
||||
return $this->protocolVersion;
|
||||
}
|
||||
|
||||
public function setProtocolVersion($protocol)
|
||||
{
|
||||
$this->protocolVersion = $protocol;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPath()
|
||||
{
|
||||
return '/' . ltrim($this->url->getPath(), '/');
|
||||
}
|
||||
|
||||
public function setPath($path)
|
||||
{
|
||||
$this->url->setPath($path);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPort()
|
||||
{
|
||||
return $this->url->getPort();
|
||||
}
|
||||
|
||||
public function setPort($port)
|
||||
{
|
||||
$this->url->setPort($port);
|
||||
|
||||
// Include the port in the Host header if it is not the default port for the scheme of the URL
|
||||
$scheme = $this->url->getScheme();
|
||||
if (($scheme == 'http' && $port != 80) || ($scheme == 'https' && $port != 443)) {
|
||||
$this->headers['host'] = $this->headerFactory->createHeader('Host', $this->url->getHost() . ':' . $port);
|
||||
} else {
|
||||
$this->headers['host'] = $this->headerFactory->createHeader('Host', $this->url->getHost());
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getUsername()
|
||||
{
|
||||
return $this->username;
|
||||
}
|
||||
|
||||
public function getPassword()
|
||||
{
|
||||
return $this->password;
|
||||
}
|
||||
|
||||
public function setAuth($user, $password = '', $scheme = CURLAUTH_BASIC)
|
||||
{
|
||||
static $authMap = array(
|
||||
'basic' => CURLAUTH_BASIC,
|
||||
'digest' => CURLAUTH_DIGEST,
|
||||
'ntlm' => CURLAUTH_NTLM,
|
||||
'any' => CURLAUTH_ANY
|
||||
);
|
||||
|
||||
// If we got false or null, disable authentication
|
||||
if (!$user) {
|
||||
$this->password = $this->username = null;
|
||||
$this->removeHeader('Authorization');
|
||||
$this->getCurlOptions()->remove(CURLOPT_HTTPAUTH);
|
||||
return $this;
|
||||
}
|
||||
|
||||
if (!is_numeric($scheme)) {
|
||||
$scheme = strtolower($scheme);
|
||||
if (!isset($authMap[$scheme])) {
|
||||
throw new InvalidArgumentException($scheme . ' is not a valid authentication type');
|
||||
}
|
||||
$scheme = $authMap[$scheme];
|
||||
}
|
||||
|
||||
$this->username = $user;
|
||||
$this->password = $password;
|
||||
|
||||
// Bypass CURL when using basic auth to promote connection reuse
|
||||
if ($scheme == CURLAUTH_BASIC) {
|
||||
$this->getCurlOptions()->remove(CURLOPT_HTTPAUTH);
|
||||
$this->setHeader('Authorization', 'Basic ' . base64_encode($this->username . ':' . $this->password));
|
||||
} else {
|
||||
$this->getCurlOptions()
|
||||
->set(CURLOPT_HTTPAUTH, $scheme)
|
||||
->set(CURLOPT_USERPWD, $this->username . ':' . $this->password);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getResource()
|
||||
{
|
||||
$resource = $this->getPath();
|
||||
if ($query = (string) $this->url->getQuery()) {
|
||||
$resource .= '?' . $query;
|
||||
}
|
||||
|
||||
return $resource;
|
||||
}
|
||||
|
||||
public function getUrl($asObject = false)
|
||||
{
|
||||
return $asObject ? clone $this->url : (string) $this->url;
|
||||
}
|
||||
|
||||
public function getState()
|
||||
{
|
||||
return $this->state;
|
||||
}
|
||||
|
||||
public function setState($state, array $context = array())
|
||||
{
|
||||
$oldState = $this->state;
|
||||
$this->state = $state;
|
||||
|
||||
switch ($state) {
|
||||
case self::STATE_NEW:
|
||||
$this->response = null;
|
||||
break;
|
||||
case self::STATE_TRANSFER:
|
||||
if ($oldState !== $state) {
|
||||
// Fix Content-Length and Transfer-Encoding collisions
|
||||
if ($this->hasHeader('Transfer-Encoding') && $this->hasHeader('Content-Length')) {
|
||||
$this->removeHeader('Transfer-Encoding');
|
||||
}
|
||||
$this->dispatch('request.before_send', array('request' => $this));
|
||||
}
|
||||
break;
|
||||
case self::STATE_COMPLETE:
|
||||
if ($oldState !== $state) {
|
||||
$this->processResponse($context);
|
||||
$this->responseBody = null;
|
||||
}
|
||||
break;
|
||||
case self::STATE_ERROR:
|
||||
if (isset($context['exception'])) {
|
||||
$this->dispatch('request.exception', array(
|
||||
'request' => $this,
|
||||
'response' => isset($context['response']) ? $context['response'] : $this->response,
|
||||
'exception' => isset($context['exception']) ? $context['exception'] : null
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
return $this->state;
|
||||
}
|
||||
|
||||
public function getCurlOptions()
|
||||
{
|
||||
return $this->curlOptions;
|
||||
}
|
||||
|
||||
public function startResponse(Response $response)
|
||||
{
|
||||
$this->state = self::STATE_TRANSFER;
|
||||
$response->setEffectiveUrl((string) $this->getUrl());
|
||||
$this->response = $response;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setResponse(Response $response, $queued = false)
|
||||
{
|
||||
$response->setEffectiveUrl((string) $this->url);
|
||||
|
||||
if ($queued) {
|
||||
$ed = $this->getEventDispatcher();
|
||||
$ed->addListener('request.before_send', $f = function ($e) use ($response, &$f, $ed) {
|
||||
$e['request']->setResponse($response);
|
||||
$ed->removeListener('request.before_send', $f);
|
||||
}, -9999);
|
||||
} else {
|
||||
$this->response = $response;
|
||||
// If a specific response body is specified, then use it instead of the response's body
|
||||
if ($this->responseBody && !$this->responseBody->getCustomData('default') && !$response->isRedirect()) {
|
||||
$this->getResponseBody()->write((string) $this->response->getBody());
|
||||
} else {
|
||||
$this->responseBody = $this->response->getBody();
|
||||
}
|
||||
$this->setState(self::STATE_COMPLETE);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setResponseBody($body)
|
||||
{
|
||||
// Attempt to open a file for writing if a string was passed
|
||||
if (is_string($body)) {
|
||||
// @codeCoverageIgnoreStart
|
||||
if (!($body = fopen($body, 'w+'))) {
|
||||
throw new InvalidArgumentException('Could not open ' . $body . ' for writing');
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
$this->responseBody = EntityBody::factory($body);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getResponseBody()
|
||||
{
|
||||
if ($this->responseBody === null) {
|
||||
$this->responseBody = EntityBody::factory()->setCustomData('default', true);
|
||||
}
|
||||
|
||||
return $this->responseBody;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the response body is repeatable (readable + seekable)
|
||||
*
|
||||
* @return bool
|
||||
* @deprecated Use getResponseBody()->isSeekable()
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function isResponseBodyRepeatable()
|
||||
{
|
||||
Version::warn(__METHOD__ . ' is deprecated. Use $request->getResponseBody()->isRepeatable()');
|
||||
return !$this->responseBody ? true : $this->responseBody->isRepeatable();
|
||||
}
|
||||
|
||||
public function getCookies()
|
||||
{
|
||||
if ($cookie = $this->getHeader('Cookie')) {
|
||||
$data = ParserRegistry::getInstance()->getParser('cookie')->parseCookie($cookie);
|
||||
return $data['cookies'];
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
public function getCookie($name)
|
||||
{
|
||||
$cookies = $this->getCookies();
|
||||
|
||||
return isset($cookies[$name]) ? $cookies[$name] : null;
|
||||
}
|
||||
|
||||
public function addCookie($name, $value)
|
||||
{
|
||||
if (!$this->hasHeader('Cookie')) {
|
||||
$this->setHeader('Cookie', "{$name}={$value}");
|
||||
} else {
|
||||
$this->getHeader('Cookie')->add("{$name}={$value}");
|
||||
}
|
||||
|
||||
// Always use semicolons to separate multiple cookie headers
|
||||
$this->getHeader('Cookie')->setGlue(';');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeCookie($name)
|
||||
{
|
||||
if ($cookie = $this->getHeader('Cookie')) {
|
||||
foreach ($cookie as $cookieValue) {
|
||||
if (strpos($cookieValue, $name . '=') === 0) {
|
||||
$cookie->removeValue($cookieValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setEventDispatcher(EventDispatcherInterface $eventDispatcher)
|
||||
{
|
||||
$this->eventDispatcher = $eventDispatcher;
|
||||
$this->eventDispatcher->addListener('request.error', array(__CLASS__, 'onRequestError'), -255);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getEventDispatcher()
|
||||
{
|
||||
if (!$this->eventDispatcher) {
|
||||
$this->setEventDispatcher(new EventDispatcher());
|
||||
}
|
||||
|
||||
return $this->eventDispatcher;
|
||||
}
|
||||
|
||||
public function dispatch($eventName, array $context = array())
|
||||
{
|
||||
$context['request'] = $this;
|
||||
$this->getEventDispatcher()->dispatch($eventName, new Event($context));
|
||||
}
|
||||
|
||||
public function addSubscriber(EventSubscriberInterface $subscriber)
|
||||
{
|
||||
$this->getEventDispatcher()->addSubscriber($subscriber);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array containing the request and response for event notifications
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getEventArray()
|
||||
{
|
||||
return array(
|
||||
'request' => $this,
|
||||
'response' => $this->response
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a received response
|
||||
*
|
||||
* @param array $context Contextual information
|
||||
* @throws RequestException|BadResponseException on unsuccessful responses
|
||||
*/
|
||||
protected function processResponse(array $context = array())
|
||||
{
|
||||
if (!$this->response) {
|
||||
// If no response, then processResponse shouldn't have been called
|
||||
$e = new RequestException('Error completing request');
|
||||
$e->setRequest($this);
|
||||
throw $e;
|
||||
}
|
||||
|
||||
$this->state = self::STATE_COMPLETE;
|
||||
|
||||
// A request was sent, but we don't know if we'll send more or if the final response will be successful
|
||||
$this->dispatch('request.sent', $this->getEventArray() + $context);
|
||||
|
||||
// Some response processors will remove the response or reset the state (example: ExponentialBackoffPlugin)
|
||||
if ($this->state == RequestInterface::STATE_COMPLETE) {
|
||||
|
||||
// The request completed, so the HTTP transaction is complete
|
||||
$this->dispatch('request.complete', $this->getEventArray());
|
||||
|
||||
// If the response is bad, allow listeners to modify it or throw exceptions. You can change the response by
|
||||
// modifying the Event object in your listeners or calling setResponse() on the request
|
||||
if ($this->response->isError()) {
|
||||
$event = new Event($this->getEventArray());
|
||||
$this->getEventDispatcher()->dispatch('request.error', $event);
|
||||
// Allow events of request.error to quietly change the response
|
||||
if ($event['response'] !== $this->response) {
|
||||
$this->response = $event['response'];
|
||||
}
|
||||
}
|
||||
|
||||
// If a successful response was received, dispatch an event
|
||||
if ($this->response->isSuccessful()) {
|
||||
$this->dispatch('request.success', $this->getEventArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use Guzzle\Plugin\Cache\DefaultCanCacheStrategy
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function canCache()
|
||||
{
|
||||
Version::warn(__METHOD__ . ' is deprecated. Use Guzzle\Plugin\Cache\DefaultCanCacheStrategy.');
|
||||
if (class_exists('Guzzle\Plugin\Cache\DefaultCanCacheStrategy')) {
|
||||
$canCache = new \Guzzle\Plugin\Cache\DefaultCanCacheStrategy();
|
||||
return $canCache->canCacheRequest($this);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use the history plugin (not emitting a warning as this is built-into the RedirectPlugin for now)
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function setIsRedirect($isRedirect)
|
||||
{
|
||||
$this->isRedirect = $isRedirect;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use the history plugin
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function isRedirect()
|
||||
{
|
||||
Version::warn(__METHOD__ . ' is deprecated. Use the HistoryPlugin to track this.');
|
||||
return $this->isRedirect;
|
||||
}
|
||||
}
|
|
@ -1,356 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http\Message;
|
||||
|
||||
use Guzzle\Common\Collection;
|
||||
use Guzzle\Common\Exception\InvalidArgumentException;
|
||||
use Guzzle\Http\RedirectPlugin;
|
||||
use Guzzle\Http\Url;
|
||||
use Guzzle\Parser\ParserRegistry;
|
||||
use Guzzle\Plugin\Log\LogPlugin;
|
||||
|
||||
/**
|
||||
* Default HTTP request factory used to create the default {@see Request} and {@see EntityEnclosingRequest} objects.
|
||||
*/
|
||||
class RequestFactory implements RequestFactoryInterface
|
||||
{
|
||||
/** @var RequestFactory Singleton instance of the default request factory */
|
||||
protected static $instance;
|
||||
|
||||
/** @var array Hash of methods available to the class (provides fast isset() lookups) */
|
||||
protected $methods;
|
||||
|
||||
/** @var string Class to instantiate for requests with no body */
|
||||
protected $requestClass = 'Guzzle\\Http\\Message\\Request';
|
||||
|
||||
/** @var string Class to instantiate for requests with a body */
|
||||
protected $entityEnclosingRequestClass = 'Guzzle\\Http\\Message\\EntityEnclosingRequest';
|
||||
|
||||
/**
|
||||
* Get a cached instance of the default request factory
|
||||
*
|
||||
* @return RequestFactory
|
||||
*/
|
||||
public static function getInstance()
|
||||
{
|
||||
// @codeCoverageIgnoreStart
|
||||
if (!static::$instance) {
|
||||
static::$instance = new static();
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
return static::$instance;
|
||||
}
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->methods = array_flip(get_class_methods(__CLASS__));
|
||||
}
|
||||
|
||||
public function fromMessage($message)
|
||||
{
|
||||
$parsed = ParserRegistry::getInstance()->getParser('message')->parseRequest($message);
|
||||
|
||||
if (!$parsed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$request = $this->fromParts($parsed['method'], $parsed['request_url'],
|
||||
$parsed['headers'], $parsed['body'], $parsed['protocol'],
|
||||
$parsed['version']);
|
||||
|
||||
// EntityEnclosingRequest adds an "Expect: 100-Continue" header when using a raw request body for PUT or POST
|
||||
// requests. This factory method should accurately reflect the message, so here we are removing the Expect
|
||||
// header if one was not supplied in the message.
|
||||
if (!isset($parsed['headers']['Expect']) && !isset($parsed['headers']['expect'])) {
|
||||
$request->removeHeader('Expect');
|
||||
}
|
||||
|
||||
return $request;
|
||||
}
|
||||
|
||||
public function fromParts(
|
||||
$method,
|
||||
array $urlParts,
|
||||
$headers = null,
|
||||
$body = null,
|
||||
$protocol = 'HTTP',
|
||||
$protocolVersion = '1.1'
|
||||
) {
|
||||
return $this->create($method, Url::buildUrl($urlParts), $headers, $body)
|
||||
->setProtocolVersion($protocolVersion);
|
||||
}
|
||||
|
||||
public function create($method, $url, $headers = null, $body = null, array $options = array())
|
||||
{
|
||||
$method = strtoupper($method);
|
||||
|
||||
if ($method == 'GET' || $method == 'HEAD' || $method == 'TRACE' || $method == 'OPTIONS') {
|
||||
// Handle non-entity-enclosing request methods
|
||||
$request = new $this->requestClass($method, $url, $headers);
|
||||
if ($body) {
|
||||
// The body is where the response body will be stored
|
||||
$type = gettype($body);
|
||||
if ($type == 'string' || $type == 'resource' || $type == 'object') {
|
||||
$request->setResponseBody($body);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Create an entity enclosing request by default
|
||||
$request = new $this->entityEnclosingRequestClass($method, $url, $headers);
|
||||
if ($body) {
|
||||
// Add POST fields and files to an entity enclosing request if an array is used
|
||||
if (is_array($body) || $body instanceof Collection) {
|
||||
// Normalize PHP style cURL uploads with a leading '@' symbol
|
||||
foreach ($body as $key => $value) {
|
||||
if (is_string($value) && substr($value, 0, 1) == '@') {
|
||||
$request->addPostFile($key, $value);
|
||||
unset($body[$key]);
|
||||
}
|
||||
}
|
||||
// Add the fields if they are still present and not all files
|
||||
$request->addPostFields($body);
|
||||
} else {
|
||||
// Add a raw entity body body to the request
|
||||
$request->setBody($body, (string) $request->getHeader('Content-Type'));
|
||||
if ((string) $request->getHeader('Transfer-Encoding') == 'chunked') {
|
||||
$request->removeHeader('Content-Length');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($options) {
|
||||
$this->applyOptions($request, $options);
|
||||
}
|
||||
|
||||
return $request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone a request while changing the method. Emulates the behavior of
|
||||
* {@see Guzzle\Http\Message\Request::clone}, but can change the HTTP method.
|
||||
*
|
||||
* @param RequestInterface $request Request to clone
|
||||
* @param string $method Method to set
|
||||
*
|
||||
* @return RequestInterface
|
||||
*/
|
||||
public function cloneRequestWithMethod(RequestInterface $request, $method)
|
||||
{
|
||||
// Create the request with the same client if possible
|
||||
if ($client = $request->getClient()) {
|
||||
$cloned = $request->getClient()->createRequest($method, $request->getUrl(), $request->getHeaders());
|
||||
} else {
|
||||
$cloned = $this->create($method, $request->getUrl(), $request->getHeaders());
|
||||
}
|
||||
|
||||
$cloned->getCurlOptions()->replace($request->getCurlOptions()->toArray());
|
||||
$cloned->setEventDispatcher(clone $request->getEventDispatcher());
|
||||
// Ensure that that the Content-Length header is not copied if changing to GET or HEAD
|
||||
if (!($cloned instanceof EntityEnclosingRequestInterface)) {
|
||||
$cloned->removeHeader('Content-Length');
|
||||
} elseif ($request instanceof EntityEnclosingRequestInterface) {
|
||||
$cloned->setBody($request->getBody());
|
||||
}
|
||||
$cloned->getParams()->replace($request->getParams()->toArray());
|
||||
$cloned->dispatch('request.clone', array('request' => $cloned));
|
||||
|
||||
return $cloned;
|
||||
}
|
||||
|
||||
public function applyOptions(RequestInterface $request, array $options = array(), $flags = self::OPTIONS_NONE)
|
||||
{
|
||||
// Iterate over each key value pair and attempt to apply a config using function visitors
|
||||
foreach ($options as $key => $value) {
|
||||
$method = "visit_{$key}";
|
||||
if (isset($this->methods[$method])) {
|
||||
$this->{$method}($request, $value, $flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function visit_headers(RequestInterface $request, $value, $flags)
|
||||
{
|
||||
if (!is_array($value)) {
|
||||
throw new InvalidArgumentException('headers value must be an array');
|
||||
}
|
||||
|
||||
if ($flags & self::OPTIONS_AS_DEFAULTS) {
|
||||
// Merge headers in but do not overwrite existing values
|
||||
foreach ($value as $key => $header) {
|
||||
if (!$request->hasHeader($key)) {
|
||||
$request->setHeader($key, $header);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$request->addHeaders($value);
|
||||
}
|
||||
}
|
||||
|
||||
protected function visit_body(RequestInterface $request, $value, $flags)
|
||||
{
|
||||
if ($request instanceof EntityEnclosingRequestInterface) {
|
||||
$request->setBody($value);
|
||||
} else {
|
||||
throw new InvalidArgumentException('Attempting to set a body on a non-entity-enclosing request');
|
||||
}
|
||||
}
|
||||
|
||||
protected function visit_allow_redirects(RequestInterface $request, $value, $flags)
|
||||
{
|
||||
if ($value === false) {
|
||||
$request->getParams()->set(RedirectPlugin::DISABLE, true);
|
||||
}
|
||||
}
|
||||
|
||||
protected function visit_auth(RequestInterface $request, $value, $flags)
|
||||
{
|
||||
if (!is_array($value)) {
|
||||
throw new InvalidArgumentException('auth value must be an array');
|
||||
}
|
||||
|
||||
$request->setAuth($value[0], isset($value[1]) ? $value[1] : null, isset($value[2]) ? $value[2] : 'basic');
|
||||
}
|
||||
|
||||
protected function visit_query(RequestInterface $request, $value, $flags)
|
||||
{
|
||||
if (!is_array($value)) {
|
||||
throw new InvalidArgumentException('query value must be an array');
|
||||
}
|
||||
|
||||
if ($flags & self::OPTIONS_AS_DEFAULTS) {
|
||||
// Merge query string values in but do not overwrite existing values
|
||||
$query = $request->getQuery();
|
||||
$query->overwriteWith(array_diff_key($value, $query->toArray()));
|
||||
} else {
|
||||
$request->getQuery()->overwriteWith($value);
|
||||
}
|
||||
}
|
||||
|
||||
protected function visit_cookies(RequestInterface $request, $value, $flags)
|
||||
{
|
||||
if (!is_array($value)) {
|
||||
throw new InvalidArgumentException('cookies value must be an array');
|
||||
}
|
||||
|
||||
foreach ($value as $name => $v) {
|
||||
$request->addCookie($name, $v);
|
||||
}
|
||||
}
|
||||
|
||||
protected function visit_events(RequestInterface $request, $value, $flags)
|
||||
{
|
||||
if (!is_array($value)) {
|
||||
throw new InvalidArgumentException('events value must be an array');
|
||||
}
|
||||
|
||||
foreach ($value as $name => $method) {
|
||||
if (is_array($method)) {
|
||||
$request->getEventDispatcher()->addListener($name, $method[0], $method[1]);
|
||||
} else {
|
||||
$request->getEventDispatcher()->addListener($name, $method);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function visit_plugins(RequestInterface $request, $value, $flags)
|
||||
{
|
||||
if (!is_array($value)) {
|
||||
throw new InvalidArgumentException('plugins value must be an array');
|
||||
}
|
||||
|
||||
foreach ($value as $plugin) {
|
||||
$request->addSubscriber($plugin);
|
||||
}
|
||||
}
|
||||
|
||||
protected function visit_exceptions(RequestInterface $request, $value, $flags)
|
||||
{
|
||||
if ($value === false || $value === 0) {
|
||||
$dispatcher = $request->getEventDispatcher();
|
||||
foreach ($dispatcher->getListeners('request.error') as $listener) {
|
||||
if ($listener[0] == 'Guzzle\Http\Message\Request' && $listener[1] = 'onRequestError') {
|
||||
$dispatcher->removeListener('request.error', $listener);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function visit_save_to(RequestInterface $request, $value, $flags)
|
||||
{
|
||||
$request->setResponseBody($value);
|
||||
}
|
||||
|
||||
protected function visit_params(RequestInterface $request, $value, $flags)
|
||||
{
|
||||
if (!is_array($value)) {
|
||||
throw new InvalidArgumentException('params value must be an array');
|
||||
}
|
||||
|
||||
$request->getParams()->overwriteWith($value);
|
||||
}
|
||||
|
||||
protected function visit_timeout(RequestInterface $request, $value, $flags)
|
||||
{
|
||||
$request->getCurlOptions()->set(CURLOPT_TIMEOUT_MS, $value * 1000);
|
||||
}
|
||||
|
||||
protected function visit_connect_timeout(RequestInterface $request, $value, $flags)
|
||||
{
|
||||
$request->getCurlOptions()->set(CURLOPT_CONNECTTIMEOUT_MS, $value * 1000);
|
||||
}
|
||||
|
||||
protected function visit_debug(RequestInterface $request, $value, $flags)
|
||||
{
|
||||
if (class_exists('Guzzle\Plugin\Log\LogPlugin')) {
|
||||
$request->addSubscriber(LogPlugin::getDebugPlugin());
|
||||
} else {
|
||||
// @codeCoverageIgnoreStart
|
||||
$request->getCurlOptions()->set(CURLOPT_VERBOSE, true);
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
}
|
||||
|
||||
protected function visit_verify(RequestInterface $request, $value, $flags)
|
||||
{
|
||||
$curl = $request->getCurlOptions();
|
||||
if ($value === true || is_string($value)) {
|
||||
$curl[CURLOPT_SSL_VERIFYHOST] = 2;
|
||||
$curl[CURLOPT_SSL_VERIFYPEER] = true;
|
||||
if ($value !== true) {
|
||||
$curl[CURLOPT_CAINFO] = $value;
|
||||
}
|
||||
} elseif ($value === false) {
|
||||
unset($curl[CURLOPT_CAINFO]);
|
||||
$curl[CURLOPT_SSL_VERIFYHOST] = 0;
|
||||
$curl[CURLOPT_SSL_VERIFYPEER] = false;
|
||||
}
|
||||
}
|
||||
|
||||
protected function visit_proxy(RequestInterface $request, $value, $flags)
|
||||
{
|
||||
$request->getCurlOptions()->set(CURLOPT_PROXY, $value, $flags);
|
||||
}
|
||||
|
||||
protected function visit_cert(RequestInterface $request, $value, $flags)
|
||||
{
|
||||
if (is_array($value)) {
|
||||
$request->getCurlOptions()->set(CURLOPT_SSLCERT, $value[0]);
|
||||
$request->getCurlOptions()->set(CURLOPT_SSLCERTPASSWD, $value[1]);
|
||||
} else {
|
||||
$request->getCurlOptions()->set(CURLOPT_SSLCERT, $value);
|
||||
}
|
||||
}
|
||||
|
||||
protected function visit_ssl_key(RequestInterface $request, $value, $flags)
|
||||
{
|
||||
if (is_array($value)) {
|
||||
$request->getCurlOptions()->set(CURLOPT_SSLKEY, $value[0]);
|
||||
$request->getCurlOptions()->set(CURLOPT_SSLKEYPASSWD, $value[1]);
|
||||
} else {
|
||||
$request->getCurlOptions()->set(CURLOPT_SSLKEY, $value);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,105 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http\Message;
|
||||
|
||||
use Guzzle\Common\Collection;
|
||||
use Guzzle\Http\EntityBodyInterface;
|
||||
use Guzzle\Http\Url;
|
||||
|
||||
/**
|
||||
* Request factory used to create HTTP requests
|
||||
*/
|
||||
interface RequestFactoryInterface
|
||||
{
|
||||
const OPTIONS_NONE = 0;
|
||||
const OPTIONS_AS_DEFAULTS = 1;
|
||||
|
||||
/**
|
||||
* Create a new request based on an HTTP message
|
||||
*
|
||||
* @param string $message HTTP message as a string
|
||||
*
|
||||
* @return RequestInterface
|
||||
*/
|
||||
public function fromMessage($message);
|
||||
|
||||
/**
|
||||
* Create a request from URL parts as returned from parse_url()
|
||||
*
|
||||
* @param string $method HTTP method (GET, POST, PUT, HEAD, DELETE, etc)
|
||||
*
|
||||
* @param array $urlParts URL parts containing the same keys as parse_url()
|
||||
* - scheme: e.g. http
|
||||
* - host: e.g. www.guzzle-project.com
|
||||
* - port: e.g. 80
|
||||
* - user: e.g. michael
|
||||
* - pass: e.g. rocks
|
||||
* - path: e.g. / OR /index.html
|
||||
* - query: after the question mark ?
|
||||
* @param array|Collection $headers HTTP headers
|
||||
* @param string|resource|array|EntityBodyInterface $body Body to send in the request
|
||||
* @param string $protocol Protocol (HTTP, SPYDY, etc)
|
||||
* @param string $protocolVersion 1.0, 1.1, etc
|
||||
*
|
||||
* @return RequestInterface
|
||||
*/
|
||||
public function fromParts(
|
||||
$method,
|
||||
array $urlParts,
|
||||
$headers = null,
|
||||
$body = null,
|
||||
$protocol = 'HTTP',
|
||||
$protocolVersion = '1.1'
|
||||
);
|
||||
|
||||
/**
|
||||
* Create a new request based on the HTTP method
|
||||
*
|
||||
* @param string $method HTTP method (GET, POST, PUT, PATCH, HEAD, DELETE, ...)
|
||||
* @param string|Url $url HTTP URL to connect to
|
||||
* @param array|Collection $headers HTTP headers
|
||||
* @param string|resource|array|EntityBodyInterface $body Body to send in the request
|
||||
* @param array $options Array of options to apply to the request
|
||||
*
|
||||
* @return RequestInterface
|
||||
*/
|
||||
public function create($method, $url, $headers = null, $body = null, array $options = array());
|
||||
|
||||
/**
|
||||
* Apply an associative array of options to the request
|
||||
*
|
||||
* @param RequestInterface $request Request to update
|
||||
* @param array $options Options to use with the request. Available options are:
|
||||
* "headers": Associative array of headers
|
||||
* "query": Associative array of query string values to add to the request
|
||||
* "body": Body of a request, including an EntityBody, string, or array when sending POST requests.
|
||||
* "auth": Array of HTTP authentication parameters to use with the request. The array must contain the
|
||||
* username in index [0], the password in index [2], and can optionally contain the authentication type
|
||||
* in index [3]. The authentication types are: "Basic", "Digest", "NTLM", "Any" (defaults to "Basic").
|
||||
* "cookies": Associative array of cookies
|
||||
* "allow_redirects": Set to false to disable redirects
|
||||
* "save_to": String, fopen resource, or EntityBody object used to store the body of the response
|
||||
* "events": Associative array mapping event names to a closure or array of (priority, closure)
|
||||
* "plugins": Array of plugins to add to the request
|
||||
* "exceptions": Set to false to disable throwing exceptions on an HTTP level error (e.g. 404, 500, etc)
|
||||
* "params": Set custom request data parameters on a request. (Note: these are not query string parameters)
|
||||
* "timeout": Float describing the timeout of the request in seconds
|
||||
* "connect_timeout": Float describing the number of seconds to wait while trying to connect. Use 0 to wait
|
||||
* indefinitely.
|
||||
* "verify": Set to true to enable SSL cert validation (the default), false to disable, or supply the path
|
||||
* to a CA bundle to enable verification using a custom certificate.
|
||||
* "cert": Set to a string to specify the path to a file containing a PEM formatted certificate. If a
|
||||
* password is required, then set an array containing the path to the PEM file followed by the the
|
||||
* password required for the certificate.
|
||||
* "ssl_key": Specify the path to a file containing a private SSL key in PEM format. If a password is
|
||||
* required, then set an array containing the path to the SSL key followed by the password required for
|
||||
* the certificate.
|
||||
* "proxy": Specify an HTTP proxy (e.g. "http://username:password@192.168.16.1:10")
|
||||
* "debug": Set to true to display all data sent over the wire
|
||||
* @param int $flags Bitwise flags to apply when applying the options to the request. Defaults to no special
|
||||
* options. `1` (OPTIONS_AS_DEFAULTS): When specified, options will only update a request when
|
||||
* the value does not already exist on the request. This is only supported by "query" and
|
||||
* "headers". Other bitwise options may be added in the future.
|
||||
*/
|
||||
public function applyOptions(RequestInterface $request, array $options = array(), $flags = self::OPTIONS_NONE);
|
||||
}
|
|
@ -1,318 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http\Message;
|
||||
|
||||
use Guzzle\Common\Collection;
|
||||
use Guzzle\Common\HasDispatcherInterface;
|
||||
use Guzzle\Http\Exception\RequestException;
|
||||
use Guzzle\Http\ClientInterface;
|
||||
use Guzzle\Http\EntityBodyInterface;
|
||||
use Guzzle\Http\Url;
|
||||
use Guzzle\Http\QueryString;
|
||||
|
||||
/**
|
||||
* Generic HTTP request interface
|
||||
*/
|
||||
interface RequestInterface extends MessageInterface, HasDispatcherInterface
|
||||
{
|
||||
const STATE_NEW = 'new';
|
||||
const STATE_COMPLETE = 'complete';
|
||||
const STATE_TRANSFER = 'transfer';
|
||||
const STATE_ERROR = 'error';
|
||||
|
||||
const GET = 'GET';
|
||||
const PUT = 'PUT';
|
||||
const POST = 'POST';
|
||||
const DELETE = 'DELETE';
|
||||
const HEAD = 'HEAD';
|
||||
const CONNECT = 'CONNECT';
|
||||
const OPTIONS = 'OPTIONS';
|
||||
const TRACE = 'TRACE';
|
||||
const PATCH = 'PATCH';
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString();
|
||||
|
||||
/**
|
||||
* Send the request
|
||||
*
|
||||
* @return Response
|
||||
* @throws RequestException on a request error
|
||||
*/
|
||||
public function send();
|
||||
|
||||
/**
|
||||
* Set the client used to transport the request
|
||||
*
|
||||
* @param ClientInterface $client
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setClient(ClientInterface $client);
|
||||
|
||||
/**
|
||||
* Get the client used to transport the request
|
||||
*
|
||||
* @return ClientInterface $client
|
||||
*/
|
||||
public function getClient();
|
||||
|
||||
/**
|
||||
* Set the URL of the request
|
||||
*
|
||||
* @param string $url|Url Full URL to set including query string
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setUrl($url);
|
||||
|
||||
/**
|
||||
* Get the full URL of the request (e.g. 'http://www.guzzle-project.com/')
|
||||
*
|
||||
* @param bool $asObject Set to TRUE to retrieve the URL as a clone of the URL object owned by the request.
|
||||
*
|
||||
* @return string|Url
|
||||
*/
|
||||
public function getUrl($asObject = false);
|
||||
|
||||
/**
|
||||
* Get the resource part of the the request, including the path, query string, and fragment
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getResource();
|
||||
|
||||
/**
|
||||
* Get the collection of key value pairs that will be used as the query string in the request
|
||||
*
|
||||
* @return QueryString
|
||||
*/
|
||||
public function getQuery();
|
||||
|
||||
/**
|
||||
* Get the HTTP method of the request
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getMethod();
|
||||
|
||||
/**
|
||||
* Get the URI scheme of the request (http, https, ftp, etc)
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getScheme();
|
||||
|
||||
/**
|
||||
* Set the URI scheme of the request (http, https, ftp, etc)
|
||||
*
|
||||
* @param string $scheme Scheme to set
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setScheme($scheme);
|
||||
|
||||
/**
|
||||
* Get the host of the request
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getHost();
|
||||
|
||||
/**
|
||||
* Set the host of the request. Including a port in the host will modify the port of the request.
|
||||
*
|
||||
* @param string $host Host to set (e.g. www.yahoo.com, www.yahoo.com:80)
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setHost($host);
|
||||
|
||||
/**
|
||||
* Get the path of the request (e.g. '/', '/index.html')
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPath();
|
||||
|
||||
/**
|
||||
* Set the path of the request (e.g. '/', '/index.html')
|
||||
*
|
||||
* @param string|array $path Path to set or array of segments to implode
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setPath($path);
|
||||
|
||||
/**
|
||||
* Get the port that the request will be sent on if it has been set
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getPort();
|
||||
|
||||
/**
|
||||
* Set the port that the request will be sent on
|
||||
*
|
||||
* @param int $port Port number to set
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setPort($port);
|
||||
|
||||
/**
|
||||
* Get the username to pass in the URL if set
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getUsername();
|
||||
|
||||
/**
|
||||
* Get the password to pass in the URL if set
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getPassword();
|
||||
|
||||
/**
|
||||
* Set HTTP authorization parameters
|
||||
*
|
||||
* @param string|bool $user User name or false disable authentication
|
||||
* @param string $password Password
|
||||
* @param string $scheme Authentication scheme ('Basic', 'Digest', or a CURLAUTH_* constant (deprecated))
|
||||
*
|
||||
* @return self
|
||||
* @link http://www.ietf.org/rfc/rfc2617.txt
|
||||
* @link http://php.net/manual/en/function.curl-setopt.php See the available options for CURLOPT_HTTPAUTH
|
||||
* @throws RequestException
|
||||
*/
|
||||
public function setAuth($user, $password = '', $scheme = 'Basic');
|
||||
|
||||
/**
|
||||
* Get the HTTP protocol version of the request
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getProtocolVersion();
|
||||
|
||||
/**
|
||||
* Set the HTTP protocol version of the request (e.g. 1.1 or 1.0)
|
||||
*
|
||||
* @param string $protocol HTTP protocol version to use with the request
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setProtocolVersion($protocol);
|
||||
|
||||
/**
|
||||
* Get the previously received {@see Response} or NULL if the request has not been sent
|
||||
*
|
||||
* @return Response|null
|
||||
*/
|
||||
public function getResponse();
|
||||
|
||||
/**
|
||||
* Manually set a response for the request.
|
||||
*
|
||||
* This method is useful for specifying a mock response for the request or setting the response using a cache.
|
||||
* Manually setting a response will bypass the actual sending of a request.
|
||||
*
|
||||
* @param Response $response Response object to set
|
||||
* @param bool $queued Set to TRUE to keep the request in a state of not having been sent, but queue the
|
||||
* response for send()
|
||||
*
|
||||
* @return self Returns a reference to the object.
|
||||
*/
|
||||
public function setResponse(Response $response, $queued = false);
|
||||
|
||||
/**
|
||||
* The start of a response has been received for a request and the request is still in progress
|
||||
*
|
||||
* @param Response $response Response that has been received so far
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function startResponse(Response $response);
|
||||
|
||||
/**
|
||||
* Set the EntityBody that will hold a successful response message's entity body.
|
||||
*
|
||||
* This method should be invoked when you need to send the response's entity body somewhere other than the normal
|
||||
* php://temp buffer. For example, you can send the entity body to a socket, file, or some other custom stream.
|
||||
*
|
||||
* @param EntityBodyInterface|string|resource $body Response body object. Pass a string to attempt to store the
|
||||
* response body in a local file.
|
||||
* @return Request
|
||||
*/
|
||||
public function setResponseBody($body);
|
||||
|
||||
/**
|
||||
* Get the EntityBody that will hold the resulting response message's entity body. This response body will only
|
||||
* be used for successful responses. Intermediate responses (e.g. redirects) will not use the targeted response
|
||||
* body.
|
||||
*
|
||||
* @return EntityBodyInterface
|
||||
*/
|
||||
public function getResponseBody();
|
||||
|
||||
/**
|
||||
* Get the state of the request. One of 'complete', 'transfer', 'new', 'error'
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getState();
|
||||
|
||||
/**
|
||||
* Set the state of the request
|
||||
*
|
||||
* @param string $state State of the request ('complete', 'transfer', 'new', 'error')
|
||||
* @param array $context Contextual information about the state change
|
||||
*
|
||||
* @return string Returns the current state of the request (which may have changed due to events being fired)
|
||||
*/
|
||||
public function setState($state, array $context = array());
|
||||
|
||||
/**
|
||||
* Get the cURL options that will be applied when the cURL handle is created
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getCurlOptions();
|
||||
|
||||
/**
|
||||
* Get an array of Cookies
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getCookies();
|
||||
|
||||
/**
|
||||
* Get a cookie value by name
|
||||
*
|
||||
* @param string $name Cookie to retrieve
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
public function getCookie($name);
|
||||
|
||||
/**
|
||||
* Add a Cookie value by name to the Cookie header
|
||||
*
|
||||
* @param string $name Name of the cookie to add
|
||||
* @param string $value Value to set
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function addCookie($name, $value);
|
||||
|
||||
/**
|
||||
* Remove a specific cookie value by name
|
||||
*
|
||||
* @param string $name Cookie to remove by name
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function removeCookie($name);
|
||||
}
|
|
@ -1,948 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http\Message;
|
||||
|
||||
use Guzzle\Common\Version;
|
||||
use Guzzle\Common\ToArrayInterface;
|
||||
use Guzzle\Common\Exception\RuntimeException;
|
||||
use Guzzle\Http\EntityBodyInterface;
|
||||
use Guzzle\Http\EntityBody;
|
||||
use Guzzle\Http\Exception\BadResponseException;
|
||||
use Guzzle\Http\RedirectPlugin;
|
||||
use Guzzle\Parser\ParserRegistry;
|
||||
|
||||
/**
|
||||
* Guzzle HTTP response object
|
||||
*/
|
||||
class Response extends AbstractMessage implements \Serializable
|
||||
{
|
||||
/**
|
||||
* @var array Array of reason phrases and their corresponding status codes
|
||||
*/
|
||||
private static $statusTexts = array(
|
||||
100 => 'Continue',
|
||||
101 => 'Switching Protocols',
|
||||
102 => 'Processing',
|
||||
200 => 'OK',
|
||||
201 => 'Created',
|
||||
202 => 'Accepted',
|
||||
203 => 'Non-Authoritative Information',
|
||||
204 => 'No Content',
|
||||
205 => 'Reset Content',
|
||||
206 => 'Partial Content',
|
||||
207 => 'Multi-Status',
|
||||
208 => 'Already Reported',
|
||||
226 => 'IM Used',
|
||||
300 => 'Multiple Choices',
|
||||
301 => 'Moved Permanently',
|
||||
302 => 'Found',
|
||||
303 => 'See Other',
|
||||
304 => 'Not Modified',
|
||||
305 => 'Use Proxy',
|
||||
307 => 'Temporary Redirect',
|
||||
308 => 'Permanent Redirect',
|
||||
400 => 'Bad Request',
|
||||
401 => 'Unauthorized',
|
||||
402 => 'Payment Required',
|
||||
403 => 'Forbidden',
|
||||
404 => 'Not Found',
|
||||
405 => 'Method Not Allowed',
|
||||
406 => 'Not Acceptable',
|
||||
407 => 'Proxy Authentication Required',
|
||||
408 => 'Request Timeout',
|
||||
409 => 'Conflict',
|
||||
410 => 'Gone',
|
||||
411 => 'Length Required',
|
||||
412 => 'Precondition Failed',
|
||||
413 => 'Request Entity Too Large',
|
||||
414 => 'Request-URI Too Long',
|
||||
415 => 'Unsupported Media Type',
|
||||
416 => 'Requested Range Not Satisfiable',
|
||||
417 => 'Expectation Failed',
|
||||
422 => 'Unprocessable Entity',
|
||||
423 => 'Locked',
|
||||
424 => 'Failed Dependency',
|
||||
425 => 'Reserved for WebDAV advanced collections expired proposal',
|
||||
426 => 'Upgrade required',
|
||||
428 => 'Precondition Required',
|
||||
429 => 'Too Many Requests',
|
||||
431 => 'Request Header Fields Too Large',
|
||||
500 => 'Internal Server Error',
|
||||
501 => 'Not Implemented',
|
||||
502 => 'Bad Gateway',
|
||||
503 => 'Service Unavailable',
|
||||
504 => 'Gateway Timeout',
|
||||
505 => 'HTTP Version Not Supported',
|
||||
506 => 'Variant Also Negotiates (Experimental)',
|
||||
507 => 'Insufficient Storage',
|
||||
508 => 'Loop Detected',
|
||||
510 => 'Not Extended',
|
||||
511 => 'Network Authentication Required',
|
||||
);
|
||||
|
||||
/** @var EntityBodyInterface The response body */
|
||||
protected $body;
|
||||
|
||||
/** @var string The reason phrase of the response (human readable code) */
|
||||
protected $reasonPhrase;
|
||||
|
||||
/** @var string The status code of the response */
|
||||
protected $statusCode;
|
||||
|
||||
/** @var array Information about the request */
|
||||
protected $info = array();
|
||||
|
||||
/** @var string The effective URL that returned this response */
|
||||
protected $effectiveUrl;
|
||||
|
||||
/** @var array Cacheable response codes (see RFC 2616:13.4) */
|
||||
protected static $cacheResponseCodes = array(200, 203, 206, 300, 301, 410);
|
||||
|
||||
/**
|
||||
* Create a new Response based on a raw response message
|
||||
*
|
||||
* @param string $message Response message
|
||||
*
|
||||
* @return self|bool Returns false on error
|
||||
*/
|
||||
public static function fromMessage($message)
|
||||
{
|
||||
$data = ParserRegistry::getInstance()->getParser('message')->parseResponse($message);
|
||||
if (!$data) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$response = new static($data['code'], $data['headers'], $data['body']);
|
||||
$response->setProtocol($data['protocol'], $data['version'])
|
||||
->setStatus($data['code'], $data['reason_phrase']);
|
||||
|
||||
// Set the appropriate Content-Length if the one set is inaccurate (e.g. setting to X)
|
||||
$contentLength = (string) $response->getHeader('Content-Length');
|
||||
$actualLength = strlen($data['body']);
|
||||
if (strlen($data['body']) > 0 && $contentLength != $actualLength) {
|
||||
$response->setHeader('Content-Length', $actualLength);
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct the response
|
||||
*
|
||||
* @param string $statusCode The response status code (e.g. 200, 404, etc)
|
||||
* @param ToArrayInterface|array $headers The response headers
|
||||
* @param string|resource|EntityBodyInterface $body The body of the response
|
||||
*
|
||||
* @throws BadResponseException if an invalid response code is given
|
||||
*/
|
||||
public function __construct($statusCode, $headers = null, $body = null)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->setStatus($statusCode);
|
||||
$this->body = EntityBody::factory($body !== null ? $body : '');
|
||||
|
||||
if ($headers) {
|
||||
if (is_array($headers)) {
|
||||
$this->setHeaders($headers);
|
||||
} elseif ($headers instanceof ToArrayInterface) {
|
||||
$this->setHeaders($headers->toArray());
|
||||
} else {
|
||||
throw new BadResponseException('Invalid headers argument received');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->getMessage();
|
||||
}
|
||||
|
||||
public function serialize()
|
||||
{
|
||||
return json_encode(array(
|
||||
'status' => $this->statusCode,
|
||||
'body' => (string) $this->body,
|
||||
'headers' => $this->headers->toArray()
|
||||
));
|
||||
}
|
||||
|
||||
public function unserialize($serialize)
|
||||
{
|
||||
$data = json_decode($serialize, true);
|
||||
$this->__construct($data['status'], $data['headers'], $data['body']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the response entity body
|
||||
*
|
||||
* @param bool $asString Set to TRUE to return a string of the body rather than a full body object
|
||||
*
|
||||
* @return EntityBodyInterface|string
|
||||
*/
|
||||
public function getBody($asString = false)
|
||||
{
|
||||
return $asString ? (string) $this->body : $this->body;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the response entity body
|
||||
*
|
||||
* @param EntityBodyInterface|string $body Body to set
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setBody($body)
|
||||
{
|
||||
$this->body = EntityBody::factory($body);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the protocol and protocol version of the response
|
||||
*
|
||||
* @param string $protocol Response protocol
|
||||
* @param string $version Protocol version
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setProtocol($protocol, $version)
|
||||
{
|
||||
$this->protocol = $protocol;
|
||||
$this->protocolVersion = $version;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the protocol used for the response (e.g. HTTP)
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getProtocol()
|
||||
{
|
||||
return $this->protocol;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the HTTP protocol version
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getProtocolVersion()
|
||||
{
|
||||
return $this->protocolVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a cURL transfer information
|
||||
*
|
||||
* @param string $key A single statistic to check
|
||||
*
|
||||
* @return array|string|null Returns all stats if no key is set, a single stat if a key is set, or null if a key
|
||||
* is set and not found
|
||||
* @link http://www.php.net/manual/en/function.curl-getinfo.php
|
||||
*/
|
||||
public function getInfo($key = null)
|
||||
{
|
||||
if ($key === null) {
|
||||
return $this->info;
|
||||
} elseif (array_key_exists($key, $this->info)) {
|
||||
return $this->info[$key];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the transfer information
|
||||
*
|
||||
* @param array $info Array of cURL transfer stats
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setInfo(array $info)
|
||||
{
|
||||
$this->info = $info;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the response status
|
||||
*
|
||||
* @param int $statusCode Response status code to set
|
||||
* @param string $reasonPhrase Response reason phrase
|
||||
*
|
||||
* @return self
|
||||
* @throws BadResponseException when an invalid response code is received
|
||||
*/
|
||||
public function setStatus($statusCode, $reasonPhrase = '')
|
||||
{
|
||||
$this->statusCode = (int) $statusCode;
|
||||
|
||||
if (!$reasonPhrase && isset(self::$statusTexts[$this->statusCode])) {
|
||||
$this->reasonPhrase = self::$statusTexts[$this->statusCode];
|
||||
} else {
|
||||
$this->reasonPhrase = $reasonPhrase;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the response status code
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getStatusCode()
|
||||
{
|
||||
return $this->statusCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the entire response as a string
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getMessage()
|
||||
{
|
||||
$message = $this->getRawHeaders();
|
||||
|
||||
// Only include the body in the message if the size is < 2MB
|
||||
$size = $this->body->getSize();
|
||||
if ($size < 2097152) {
|
||||
$message .= (string) $this->body;
|
||||
}
|
||||
|
||||
return $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the the raw message headers as a string
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRawHeaders()
|
||||
{
|
||||
$headers = 'HTTP/1.1 ' . $this->statusCode . ' ' . $this->reasonPhrase . "\r\n";
|
||||
$lines = $this->getHeaderLines();
|
||||
if (!empty($lines)) {
|
||||
$headers .= implode("\r\n", $lines) . "\r\n";
|
||||
}
|
||||
|
||||
return $headers . "\r\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the response reason phrase- a human readable version of the numeric
|
||||
* status code
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getReasonPhrase()
|
||||
{
|
||||
return $this->reasonPhrase;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Accept-Ranges HTTP header
|
||||
*
|
||||
* @return string Returns what partial content range types this server supports.
|
||||
*/
|
||||
public function getAcceptRanges()
|
||||
{
|
||||
return (string) $this->getHeader('Accept-Ranges');
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the age of the response
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function calculateAge()
|
||||
{
|
||||
$age = $this->getHeader('Age');
|
||||
|
||||
if ($age === null && $this->getDate()) {
|
||||
$age = time() - strtotime($this->getDate());
|
||||
}
|
||||
|
||||
return $age === null ? null : (int) (string) $age;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Age HTTP header
|
||||
*
|
||||
* @return integer|null Returns the age the object has been in a proxy cache in seconds.
|
||||
*/
|
||||
public function getAge()
|
||||
{
|
||||
return (string) $this->getHeader('Age');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Allow HTTP header
|
||||
*
|
||||
* @return string|null Returns valid actions for a specified resource. To be used for a 405 Method not allowed.
|
||||
*/
|
||||
public function getAllow()
|
||||
{
|
||||
return (string) $this->getHeader('Allow');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an HTTP method is allowed by checking the Allow response header
|
||||
*
|
||||
* @param string $method Method to check
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isMethodAllowed($method)
|
||||
{
|
||||
$allow = $this->getHeader('Allow');
|
||||
if ($allow) {
|
||||
foreach (explode(',', $allow) as $allowable) {
|
||||
if (!strcasecmp(trim($allowable), $method)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Cache-Control HTTP header
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCacheControl()
|
||||
{
|
||||
return (string) $this->getHeader('Cache-Control');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Connection HTTP header
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getConnection()
|
||||
{
|
||||
return (string) $this->getHeader('Connection');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Content-Encoding HTTP header
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getContentEncoding()
|
||||
{
|
||||
return (string) $this->getHeader('Content-Encoding');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Content-Language HTTP header
|
||||
*
|
||||
* @return string|null Returns the language the content is in.
|
||||
*/
|
||||
public function getContentLanguage()
|
||||
{
|
||||
return (string) $this->getHeader('Content-Language');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Content-Length HTTP header
|
||||
*
|
||||
* @return integer Returns the length of the response body in bytes
|
||||
*/
|
||||
public function getContentLength()
|
||||
{
|
||||
return (int) (string) $this->getHeader('Content-Length');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Content-Location HTTP header
|
||||
*
|
||||
* @return string|null Returns an alternate location for the returned data (e.g /index.htm)
|
||||
*/
|
||||
public function getContentLocation()
|
||||
{
|
||||
return (string) $this->getHeader('Content-Location');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Content-Disposition HTTP header
|
||||
*
|
||||
* @return string|null Returns the Content-Disposition header
|
||||
*/
|
||||
public function getContentDisposition()
|
||||
{
|
||||
return (string) $this->getHeader('Content-Disposition');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Content-MD5 HTTP header
|
||||
*
|
||||
* @return string|null Returns a Base64-encoded binary MD5 sum of the content of the response.
|
||||
*/
|
||||
public function getContentMd5()
|
||||
{
|
||||
return (string) $this->getHeader('Content-MD5');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Content-Range HTTP header
|
||||
*
|
||||
* @return string Returns where in a full body message this partial message belongs (e.g. bytes 21010-47021/47022).
|
||||
*/
|
||||
public function getContentRange()
|
||||
{
|
||||
return (string) $this->getHeader('Content-Range');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Content-Type HTTP header
|
||||
*
|
||||
* @return string Returns the mime type of this content.
|
||||
*/
|
||||
public function getContentType()
|
||||
{
|
||||
return (string) $this->getHeader('Content-Type');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the Content-Type is of a certain type. This is useful if the
|
||||
* Content-Type header contains charset information and you need to know if
|
||||
* the Content-Type matches a particular type.
|
||||
*
|
||||
* @param string $type Content type to check against
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isContentType($type)
|
||||
{
|
||||
return stripos($this->getHeader('Content-Type'), $type) !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Date HTTP header
|
||||
*
|
||||
* @return string|null Returns the date and time that the message was sent.
|
||||
*/
|
||||
public function getDate()
|
||||
{
|
||||
return (string) $this->getHeader('Date');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ETag HTTP header
|
||||
*
|
||||
* @return string|null Returns an identifier for a specific version of a resource, often a Message digest.
|
||||
*/
|
||||
public function getEtag()
|
||||
{
|
||||
return (string) $this->getHeader('ETag');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Expires HTTP header
|
||||
*
|
||||
* @return string|null Returns the date/time after which the response is considered stale.
|
||||
*/
|
||||
public function getExpires()
|
||||
{
|
||||
return (string) $this->getHeader('Expires');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Last-Modified HTTP header
|
||||
*
|
||||
* @return string|null Returns the last modified date for the requested object, in RFC 2822 format
|
||||
* (e.g. Tue, 15 Nov 1994 12:45:26 GMT)
|
||||
*/
|
||||
public function getLastModified()
|
||||
{
|
||||
return (string) $this->getHeader('Last-Modified');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Location HTTP header
|
||||
*
|
||||
* @return string|null Used in redirection, or when a new resource has been created.
|
||||
*/
|
||||
public function getLocation()
|
||||
{
|
||||
return (string) $this->getHeader('Location');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Pragma HTTP header
|
||||
*
|
||||
* @return Header|null Returns the implementation-specific headers that may have various effects anywhere along
|
||||
* the request-response chain.
|
||||
*/
|
||||
public function getPragma()
|
||||
{
|
||||
return (string) $this->getHeader('Pragma');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Proxy-Authenticate HTTP header
|
||||
*
|
||||
* @return string|null Authentication to access the proxy (e.g. Basic)
|
||||
*/
|
||||
public function getProxyAuthenticate()
|
||||
{
|
||||
return (string) $this->getHeader('Proxy-Authenticate');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Retry-After HTTP header
|
||||
*
|
||||
* @return int|null If an entity is temporarily unavailable, this instructs the client to try again after a
|
||||
* specified period of time.
|
||||
*/
|
||||
public function getRetryAfter()
|
||||
{
|
||||
return (string) $this->getHeader('Retry-After');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Server HTTP header
|
||||
*
|
||||
* @return string|null A name for the server
|
||||
*/
|
||||
public function getServer()
|
||||
{
|
||||
return (string) $this->getHeader('Server');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Set-Cookie HTTP header
|
||||
*
|
||||
* @return string|null An HTTP cookie.
|
||||
*/
|
||||
public function getSetCookie()
|
||||
{
|
||||
return (string) $this->getHeader('Set-Cookie');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Trailer HTTP header
|
||||
*
|
||||
* @return string|null The Trailer general field value indicates that the given set of header fields is present in
|
||||
* the trailer of a message encoded with chunked transfer-coding.
|
||||
*/
|
||||
public function getTrailer()
|
||||
{
|
||||
return (string) $this->getHeader('Trailer');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Transfer-Encoding HTTP header
|
||||
*
|
||||
* @return string|null The form of encoding used to safely transfer the entity to the user
|
||||
*/
|
||||
public function getTransferEncoding()
|
||||
{
|
||||
return (string) $this->getHeader('Transfer-Encoding');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Vary HTTP header
|
||||
*
|
||||
* @return string|null Tells downstream proxies how to match future request headers to decide whether the cached
|
||||
* response can be used rather than requesting a fresh one from the origin server.
|
||||
*/
|
||||
public function getVary()
|
||||
{
|
||||
return (string) $this->getHeader('Vary');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Via HTTP header
|
||||
*
|
||||
* @return string|null Informs the client of proxies through which the response was sent.
|
||||
*/
|
||||
public function getVia()
|
||||
{
|
||||
return (string) $this->getHeader('Via');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Warning HTTP header
|
||||
*
|
||||
* @return string|null A general warning about possible problems with the entity body
|
||||
*/
|
||||
public function getWarning()
|
||||
{
|
||||
return (string) $this->getHeader('Warning');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the WWW-Authenticate HTTP header
|
||||
*
|
||||
* @return string|null Indicates the authentication scheme that should be used to access the requested entity
|
||||
*/
|
||||
public function getWwwAuthenticate()
|
||||
{
|
||||
return (string) $this->getHeader('WWW-Authenticate');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if HTTP Status code is a Client Error (4xx)
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isClientError()
|
||||
{
|
||||
return $this->statusCode >= 400 && $this->statusCode < 500;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if HTTP Status code is Server OR Client Error (4xx or 5xx)
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isError()
|
||||
{
|
||||
return $this->isClientError() || $this->isServerError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if HTTP Status code is Information (1xx)
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isInformational()
|
||||
{
|
||||
return $this->statusCode < 200;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if HTTP Status code is a Redirect (3xx)
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isRedirect()
|
||||
{
|
||||
return $this->statusCode >= 300 && $this->statusCode < 400;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if HTTP Status code is Server Error (5xx)
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isServerError()
|
||||
{
|
||||
return $this->statusCode >= 500 && $this->statusCode < 600;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if HTTP Status code is Successful (2xx | 304)
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isSuccessful()
|
||||
{
|
||||
return ($this->statusCode >= 200 && $this->statusCode < 300) || $this->statusCode == 304;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the response can be cached based on the response headers
|
||||
*
|
||||
* @return bool Returns TRUE if the response can be cached or false if not
|
||||
*/
|
||||
public function canCache()
|
||||
{
|
||||
// Check if the response is cacheable based on the code
|
||||
if (!in_array((int) $this->getStatusCode(), self::$cacheResponseCodes)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure a valid body was returned and can be cached
|
||||
if ((!$this->getBody()->isReadable() || !$this->getBody()->isSeekable())
|
||||
&& ($this->getContentLength() > 0 || $this->getTransferEncoding() == 'chunked')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Never cache no-store resources (this is a private cache, so private
|
||||
// can be cached)
|
||||
if ($this->getHeader('Cache-Control') && $this->getHeader('Cache-Control')->hasDirective('no-store')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->isFresh() || $this->getFreshness() === null || $this->canValidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of seconds from the current time in which this response is still considered fresh
|
||||
*
|
||||
* @return int|null Returns the number of seconds
|
||||
*/
|
||||
public function getMaxAge()
|
||||
{
|
||||
if ($header = $this->getHeader('Cache-Control')) {
|
||||
// s-max-age, then max-age, then Expires
|
||||
if ($age = $header->getDirective('s-maxage')) {
|
||||
return $age;
|
||||
}
|
||||
if ($age = $header->getDirective('max-age')) {
|
||||
return $age;
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->getHeader('Expires')) {
|
||||
return strtotime($this->getExpires()) - time();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the response is considered fresh.
|
||||
*
|
||||
* A response is considered fresh when its age is less than or equal to the freshness lifetime (maximum age) of the
|
||||
* response.
|
||||
*
|
||||
* @return bool|null
|
||||
*/
|
||||
public function isFresh()
|
||||
{
|
||||
$fresh = $this->getFreshness();
|
||||
|
||||
return $fresh === null ? null : $fresh >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the response can be validated against the origin server using a conditional GET request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function canValidate()
|
||||
{
|
||||
return $this->getEtag() || $this->getLastModified();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the freshness of the response by returning the difference of the maximum lifetime of the response and the
|
||||
* age of the response (max-age - age).
|
||||
*
|
||||
* Freshness values less than 0 mean that the response is no longer fresh and is ABS(freshness) seconds expired.
|
||||
* Freshness values of greater than zero is the number of seconds until the response is no longer fresh. A NULL
|
||||
* result means that no freshness information is available.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getFreshness()
|
||||
{
|
||||
$maxAge = $this->getMaxAge();
|
||||
$age = $this->calculateAge();
|
||||
|
||||
return $maxAge && $age ? ($maxAge - $age) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the JSON response body and return an array
|
||||
*
|
||||
* @return array|string|int|bool|float
|
||||
* @throws RuntimeException if the response body is not in JSON format
|
||||
*/
|
||||
public function json()
|
||||
{
|
||||
$data = json_decode((string) $this->body, true);
|
||||
if (JSON_ERROR_NONE !== json_last_error()) {
|
||||
throw new RuntimeException('Unable to parse response body into JSON: ' . json_last_error());
|
||||
}
|
||||
|
||||
return $data === null ? array() : $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the XML response body and return a SimpleXMLElement
|
||||
*
|
||||
* @return \SimpleXMLElement
|
||||
* @throws RuntimeException if the response body is not in XML format
|
||||
*/
|
||||
public function xml()
|
||||
{
|
||||
try {
|
||||
// Allow XML to be retrieved even if there is no response body
|
||||
$xml = new \SimpleXMLElement((string) $this->body ?: '<root />');
|
||||
} catch (\Exception $e) {
|
||||
throw new RuntimeException('Unable to parse response body into XML: ' . $e->getMessage());
|
||||
}
|
||||
|
||||
return $xml;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the redirect count of this response
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getRedirectCount()
|
||||
{
|
||||
return (int) $this->params->get(RedirectPlugin::REDIRECT_COUNT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the effective URL that resulted in this response (e.g. the last redirect URL)
|
||||
*
|
||||
* @param string $url The effective URL
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setEffectiveUrl($url)
|
||||
{
|
||||
$this->effectiveUrl = $url;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the effective URL that resulted in this response (e.g. the last redirect URL)
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getEffectiveUrl()
|
||||
{
|
||||
return $this->effectiveUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function getPreviousResponse()
|
||||
{
|
||||
Version::warn(__METHOD__ . ' is deprecated. Use the HistoryPlugin.');
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function setRequest($request)
|
||||
{
|
||||
Version::warn(__METHOD__ . ' is deprecated');
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function getRequest()
|
||||
{
|
||||
Version::warn(__METHOD__ . ' is deprecated');
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http\QueryAggregator;
|
||||
|
||||
use Guzzle\Http\QueryString;
|
||||
|
||||
/**
|
||||
* Aggregates nested query string variables using commas
|
||||
*/
|
||||
class CommaAggregator implements QueryAggregatorInterface
|
||||
{
|
||||
public function aggregate($key, $value, QueryString $query)
|
||||
{
|
||||
if ($query->isUrlEncoding()) {
|
||||
return array($query->encodeValue($key) => implode(',', array_map(array($query, 'encodeValue'), $value)));
|
||||
} else {
|
||||
return array($key => implode(',', $value));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http\QueryAggregator;
|
||||
|
||||
use Guzzle\Http\QueryString;
|
||||
|
||||
/**
|
||||
* Does not aggregate nested query string values and allows duplicates in the resulting array
|
||||
*
|
||||
* Example: http://test.com?q=1&q=2
|
||||
*/
|
||||
class DuplicateAggregator implements QueryAggregatorInterface
|
||||
{
|
||||
public function aggregate($key, $value, QueryString $query)
|
||||
{
|
||||
if ($query->isUrlEncoding()) {
|
||||
return array($query->encodeValue($key) => array_map(array($query, 'encodeValue'), $value));
|
||||
} else {
|
||||
return array($key => $value);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http\QueryAggregator;
|
||||
|
||||
use Guzzle\Http\QueryString;
|
||||
|
||||
/**
|
||||
* Aggregates nested query string variables using PHP style []
|
||||
*/
|
||||
class PhpAggregator implements QueryAggregatorInterface
|
||||
{
|
||||
public function aggregate($key, $value, QueryString $query)
|
||||
{
|
||||
$ret = array();
|
||||
|
||||
foreach ($value as $k => $v) {
|
||||
$k = "{$key}[{$k}]";
|
||||
if (is_array($v)) {
|
||||
$ret = array_merge($ret, self::aggregate($k, $v, $query));
|
||||
} else {
|
||||
$ret[$query->encodeValue($k)] = $query->encodeValue($v);
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http\QueryAggregator;
|
||||
|
||||
use Guzzle\Http\QueryString;
|
||||
|
||||
/**
|
||||
* Interface used for aggregating nested query string variables into a flattened array of key value pairs
|
||||
*/
|
||||
interface QueryAggregatorInterface
|
||||
{
|
||||
/**
|
||||
* Aggregate multi-valued parameters into a flattened associative array
|
||||
*
|
||||
* @param string $key The name of the query string parameter
|
||||
* @param array $value The values of the parameter
|
||||
* @param QueryString $query The query string that is being aggregated
|
||||
*
|
||||
* @return array Returns an array of the combined values
|
||||
*/
|
||||
public function aggregate($key, $value, QueryString $query);
|
||||
}
|
|
@ -1,267 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http;
|
||||
|
||||
use Guzzle\Common\Collection;
|
||||
use Guzzle\Http\QueryAggregator\QueryAggregatorInterface;
|
||||
use Guzzle\Http\QueryAggregator\PhpAggregator;
|
||||
|
||||
/**
|
||||
* Query string object to handle managing query string parameters and aggregating those parameters together as a string.
|
||||
*/
|
||||
class QueryString extends Collection
|
||||
{
|
||||
/** @var string Used to URL encode with rawurlencode */
|
||||
const RFC_3986 = 'RFC 3986';
|
||||
|
||||
/** @var string Used to encode with urlencode */
|
||||
const FORM_URLENCODED = 'application/x-www-form-urlencoded';
|
||||
|
||||
/** @var string Constant used to create blank query string values (e.g. ?foo) */
|
||||
const BLANK = "_guzzle_blank_";
|
||||
|
||||
/** @var string The query string field separator (e.g. '&') */
|
||||
protected $fieldSeparator = '&';
|
||||
|
||||
/** @var string The query string value separator (e.g. '=') */
|
||||
protected $valueSeparator = '=';
|
||||
|
||||
/** @var bool URL encode fields and values */
|
||||
protected $urlEncode = 'RFC 3986';
|
||||
|
||||
/** @var QueryAggregatorInterface */
|
||||
protected $aggregator;
|
||||
|
||||
/** @var array Cached PHP aggregator */
|
||||
protected static $defaultAggregator = null;
|
||||
|
||||
/**
|
||||
* Parse a query string into a QueryString object
|
||||
*
|
||||
* @param string $query Query string to parse
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public static function fromString($query)
|
||||
{
|
||||
$q = new static();
|
||||
|
||||
if ($query || $query === '0') {
|
||||
if ($query[0] == '?') {
|
||||
$query = substr($query, 1);
|
||||
}
|
||||
foreach (explode('&', $query) as $kvp) {
|
||||
$parts = explode('=', $kvp, 2);
|
||||
$key = rawurldecode($parts[0]);
|
||||
|
||||
if ($paramIsPhpStyleArray = substr($key, -2) == '[]') {
|
||||
$key = substr($key, 0, -2);
|
||||
}
|
||||
|
||||
if (isset($parts[1])) {
|
||||
$value = rawurldecode(str_replace('+', '%20', $parts[1]));
|
||||
if ($paramIsPhpStyleArray && !$q->hasKey($key)) {
|
||||
$value = array($value);
|
||||
}
|
||||
$q->add($key, $value);
|
||||
} else {
|
||||
$q->add($key, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $q;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the query string parameters to a query string string
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
if (!$this->data) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$queryString = '';
|
||||
|
||||
foreach ($this->prepareData($this->data) as $name => $value) {
|
||||
foreach ((array) $value as $v) {
|
||||
if ($queryString) {
|
||||
$queryString .= $this->fieldSeparator;
|
||||
}
|
||||
$queryString .= $name;
|
||||
if ($v !== self::BLANK) {
|
||||
$queryString .= $this->valueSeparator . $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $queryString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the query string field separator
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFieldSeparator()
|
||||
{
|
||||
return $this->fieldSeparator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the query string value separator
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getValueSeparator()
|
||||
{
|
||||
return $this->valueSeparator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of URL encoding used by the query string
|
||||
*
|
||||
* One of: false, "RFC 3986", or "application/x-www-form-urlencoded"
|
||||
*
|
||||
* @return bool|string
|
||||
*/
|
||||
public function getUrlEncoding()
|
||||
{
|
||||
return $this->urlEncode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true or false if using URL encoding
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isUrlEncoding()
|
||||
{
|
||||
return $this->urlEncode !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a function for combining multi-valued query string parameters into a single or multiple fields
|
||||
*
|
||||
* @param null|QueryAggregatorInterface $aggregator Pass in a QueryAggregatorInterface object to handle converting
|
||||
* deeply nested query string variables into a flattened array.
|
||||
* Pass null to use the default PHP style aggregator. For legacy
|
||||
* reasons, this function accepts a callable that must accepts a
|
||||
* $key, $value, and query object.
|
||||
* @return self
|
||||
* @see \Guzzle\Http\QueryString::aggregateUsingComma()
|
||||
*/
|
||||
public function setAggregator(QueryAggregatorInterface $aggregator = null)
|
||||
{
|
||||
// Use the default aggregator if none was set
|
||||
if (!$aggregator) {
|
||||
if (!self::$defaultAggregator) {
|
||||
self::$defaultAggregator = new PhpAggregator();
|
||||
}
|
||||
$aggregator = self::$defaultAggregator;
|
||||
}
|
||||
|
||||
$this->aggregator = $aggregator;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether or not field names and values should be rawurlencoded
|
||||
*
|
||||
* @param bool|string $encode Set to TRUE to use RFC 3986 encoding (rawurlencode), false to disable encoding, or
|
||||
* form_urlencoding to use application/x-www-form-urlencoded encoding (urlencode)
|
||||
* @return self
|
||||
*/
|
||||
public function useUrlEncoding($encode)
|
||||
{
|
||||
$this->urlEncode = ($encode === true) ? self::RFC_3986 : $encode;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the query string separator
|
||||
*
|
||||
* @param string $separator The query string separator that will separate fields
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setFieldSeparator($separator)
|
||||
{
|
||||
$this->fieldSeparator = $separator;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the query string value separator
|
||||
*
|
||||
* @param string $separator The query string separator that will separate values from fields
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setValueSeparator($separator)
|
||||
{
|
||||
$this->valueSeparator = $separator;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of url encoded field names and values
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function urlEncode()
|
||||
{
|
||||
return $this->prepareData($this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* URL encodes a value based on the url encoding type of the query string object
|
||||
*
|
||||
* @param string $value Value to encode
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function encodeValue($value)
|
||||
{
|
||||
if ($this->urlEncode == self::RFC_3986) {
|
||||
return rawurlencode($value);
|
||||
} elseif ($this->urlEncode == self::FORM_URLENCODED) {
|
||||
return urlencode($value);
|
||||
} else {
|
||||
return (string) $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Url encode parameter data and convert nested query strings into a flattened hash.
|
||||
*
|
||||
* @param array $data The data to encode
|
||||
*
|
||||
* @return array Returns an array of encoded values and keys
|
||||
*/
|
||||
protected function prepareData(array $data)
|
||||
{
|
||||
// If no aggregator is present then set the default
|
||||
if (!$this->aggregator) {
|
||||
$this->setAggregator(null);
|
||||
}
|
||||
|
||||
$temp = array();
|
||||
foreach ($data as $key => $value) {
|
||||
if (is_array($value)) {
|
||||
$temp = array_merge($temp, $this->aggregator->aggregate($key, $value, $this));
|
||||
} else {
|
||||
$temp[$this->encodeValue($key)] = $this->encodeValue($value);
|
||||
}
|
||||
}
|
||||
|
||||
return $temp;
|
||||
}
|
||||
}
|
|
@ -1,106 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http;
|
||||
|
||||
/**
|
||||
* EntityBody decorator used to return only a subset of an entity body
|
||||
*/
|
||||
class ReadLimitEntityBody extends AbstractEntityBodyDecorator
|
||||
{
|
||||
/** @var int Limit the number of bytes that can be read */
|
||||
protected $limit;
|
||||
|
||||
/** @var int Offset to start reading from */
|
||||
protected $offset;
|
||||
|
||||
/**
|
||||
* @param EntityBodyInterface $body Body to wrap
|
||||
* @param int $limit Total number of bytes to allow to be read from the stream
|
||||
* @param int $offset Position to seek to before reading (only works on seekable streams)
|
||||
*/
|
||||
public function __construct(EntityBodyInterface $body, $limit, $offset = 0)
|
||||
{
|
||||
parent::__construct($body);
|
||||
$this->setLimit($limit)->setOffset($offset);
|
||||
$this->body->seek($offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns only a subset of the decorated entity body when cast as a string
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return substr((string) $this->body, $this->offset, $this->limit) ?: '';
|
||||
}
|
||||
|
||||
public function isConsumed()
|
||||
{
|
||||
return (($this->offset + $this->limit) - $this->body->ftell()) <= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Content-Length of the limited subset of data
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getContentLength()
|
||||
{
|
||||
$length = $this->body->getContentLength();
|
||||
|
||||
return $length === false
|
||||
? $this->limit
|
||||
: min($this->limit, min($length, $this->offset + $this->limit) - $this->offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow for a bounded seek on the read limited entity body
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function seek($offset, $whence = SEEK_SET)
|
||||
{
|
||||
return $whence === SEEK_SET
|
||||
? $this->body->seek(max($this->offset, min($this->offset + $this->limit, $offset)))
|
||||
: false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the offset to start limiting from
|
||||
*
|
||||
* @param int $offset Offset to seek to and begin byte limiting from
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setOffset($offset)
|
||||
{
|
||||
$this->body->seek($offset);
|
||||
$this->offset = $offset;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the limit of bytes that the decorator allows to be read from the stream
|
||||
*
|
||||
* @param int $limit Total number of bytes to allow to be read from the stream
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setLimit($limit)
|
||||
{
|
||||
$this->limit = $limit;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function read($length)
|
||||
{
|
||||
// Check if the current position is less than the total allowed bytes + original offset
|
||||
$remaining = ($this->offset + $this->limit) - $this->body->ftell();
|
||||
if ($remaining > 0) {
|
||||
// Only return the amount of requested data, ensuring that the byte limit is not exceeded
|
||||
return $this->body->read(min($remaining, $length));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,250 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http;
|
||||
|
||||
use Guzzle\Common\Event;
|
||||
use Guzzle\Http\Exception\BadResponseException;
|
||||
use Guzzle\Http\Url;
|
||||
use Guzzle\Http\Message\Response;
|
||||
use Guzzle\Http\Message\RequestInterface;
|
||||
use Guzzle\Http\Message\RequestFactory;
|
||||
use Guzzle\Http\Message\EntityEnclosingRequestInterface;
|
||||
use Guzzle\Http\Exception\TooManyRedirectsException;
|
||||
use Guzzle\Http\Exception\CouldNotRewindStreamException;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
/**
|
||||
* Plugin to implement HTTP redirects. Can redirect like a web browser or using strict RFC 2616 compliance
|
||||
*/
|
||||
class RedirectPlugin implements EventSubscriberInterface
|
||||
{
|
||||
const REDIRECT_COUNT = 'redirect.count';
|
||||
const MAX_REDIRECTS = 'redirect.max';
|
||||
const STRICT_REDIRECTS = 'redirect.strict';
|
||||
const PARENT_REQUEST = 'redirect.parent_request';
|
||||
const DISABLE = 'redirect.disable';
|
||||
|
||||
/**
|
||||
* @var int Default number of redirects allowed when no setting is supplied by a request
|
||||
*/
|
||||
protected $defaultMaxRedirects = 5;
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
'request.sent' => array('onRequestSent', 100),
|
||||
'request.clone' => 'cleanupRequest',
|
||||
'request.before_send' => 'cleanupRequest'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up the parameters of a request when it is cloned
|
||||
*
|
||||
* @param Event $event Event emitted
|
||||
*/
|
||||
public function cleanupRequest(Event $event)
|
||||
{
|
||||
$params = $event['request']->getParams();
|
||||
unset($params[self::REDIRECT_COUNT]);
|
||||
unset($params[self::PARENT_REQUEST]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a request receives a redirect response
|
||||
*
|
||||
* @param Event $event Event emitted
|
||||
*/
|
||||
public function onRequestSent(Event $event)
|
||||
{
|
||||
$response = $event['response'];
|
||||
$request = $event['request'];
|
||||
|
||||
// Only act on redirect requests with Location headers
|
||||
if (!$response || $request->getParams()->get(self::DISABLE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Trace the original request based on parameter history
|
||||
$original = $this->getOriginalRequest($request);
|
||||
|
||||
// Terminating condition to set the effective repsonse on the original request
|
||||
if (!$response->isRedirect() || !$response->hasHeader('Location')) {
|
||||
if ($request !== $original) {
|
||||
// This is a terminating redirect response, so set it on the original request
|
||||
$response->getParams()->set(self::REDIRECT_COUNT, $original->getParams()->get(self::REDIRECT_COUNT));
|
||||
$original->setResponse($response);
|
||||
$response->setEffectiveUrl($request->getUrl());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
$this->sendRedirectRequest($original, $request, $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the original request that initiated a series of redirects
|
||||
*
|
||||
* @param RequestInterface $request Request to get the original request from
|
||||
*
|
||||
* @return RequestInterface
|
||||
*/
|
||||
protected function getOriginalRequest(RequestInterface $request)
|
||||
{
|
||||
$original = $request;
|
||||
// The number of redirects is held on the original request, so determine which request that is
|
||||
while ($parent = $original->getParams()->get(self::PARENT_REQUEST)) {
|
||||
$original = $parent;
|
||||
}
|
||||
|
||||
return $original;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a redirect request for a specific request object
|
||||
*
|
||||
* Takes into account strict RFC compliant redirection (e.g. redirect POST with POST) vs doing what most clients do
|
||||
* (e.g. redirect POST with GET).
|
||||
*
|
||||
* @param RequestInterface $request Request being redirected
|
||||
* @param RequestInterface $original Original request
|
||||
* @param int $statusCode Status code of the redirect
|
||||
* @param string $location Location header of the redirect
|
||||
*
|
||||
* @return RequestInterface Returns a new redirect request
|
||||
* @throws CouldNotRewindStreamException If the body needs to be rewound but cannot
|
||||
*/
|
||||
protected function createRedirectRequest(
|
||||
RequestInterface $request,
|
||||
$statusCode,
|
||||
$location,
|
||||
RequestInterface $original
|
||||
) {
|
||||
$redirectRequest = null;
|
||||
$strict = $original->getParams()->get(self::STRICT_REDIRECTS);
|
||||
|
||||
// Use a GET request if this is an entity enclosing request and we are not forcing RFC compliance, but rather
|
||||
// emulating what all browsers would do
|
||||
if ($request instanceof EntityEnclosingRequestInterface && !$strict && $statusCode <= 302) {
|
||||
$redirectRequest = RequestFactory::getInstance()->cloneRequestWithMethod($request, 'GET');
|
||||
} else {
|
||||
$redirectRequest = clone $request;
|
||||
}
|
||||
|
||||
$redirectRequest->setIsRedirect(true);
|
||||
// Always use the same response body when redirecting
|
||||
$redirectRequest->setResponseBody($request->getResponseBody());
|
||||
|
||||
$location = Url::factory($location);
|
||||
// If the location is not absolute, then combine it with the original URL
|
||||
if (!$location->isAbsolute()) {
|
||||
$originalUrl = $redirectRequest->getUrl(true);
|
||||
// Remove query string parameters and just take what is present on the redirect Location header
|
||||
$originalUrl->getQuery()->clear();
|
||||
$location = $originalUrl->combine((string) $location);
|
||||
}
|
||||
|
||||
$redirectRequest->setUrl($location);
|
||||
|
||||
// Add the parent request to the request before it sends (make sure it's before the onRequestClone event too)
|
||||
$redirectRequest->getEventDispatcher()->addListener(
|
||||
'request.before_send',
|
||||
$func = function ($e) use (&$func, $request, $redirectRequest) {
|
||||
$redirectRequest->getEventDispatcher()->removeListener('request.before_send', $func);
|
||||
$e['request']->getParams()->set(RedirectPlugin::PARENT_REQUEST, $request);
|
||||
}
|
||||
);
|
||||
|
||||
// Rewind the entity body of the request if needed
|
||||
if ($redirectRequest instanceof EntityEnclosingRequestInterface && $redirectRequest->getBody()) {
|
||||
$body = $redirectRequest->getBody();
|
||||
// Only rewind the body if some of it has been read already, and throw an exception if the rewind fails
|
||||
if ($body->ftell() && !$body->rewind()) {
|
||||
throw new CouldNotRewindStreamException(
|
||||
'Unable to rewind the non-seekable entity body of the request after redirecting. cURL probably '
|
||||
. 'sent part of body before the redirect occurred. Try adding acustom rewind function using on the '
|
||||
. 'entity body of the request using setRewindFunction().'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $redirectRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the request for redirection and enforce the maximum number of allowed redirects per client
|
||||
*
|
||||
* @param RequestInterface $original Origina request
|
||||
* @param RequestInterface $request Request to prepare and validate
|
||||
* @param Response $response The current response
|
||||
*
|
||||
* @return RequestInterface
|
||||
*/
|
||||
protected function prepareRedirection(RequestInterface $original, RequestInterface $request, Response $response)
|
||||
{
|
||||
$params = $original->getParams();
|
||||
// This is a new redirect, so increment the redirect counter
|
||||
$current = $params[self::REDIRECT_COUNT] + 1;
|
||||
$params[self::REDIRECT_COUNT] = $current;
|
||||
// Use a provided maximum value or default to a max redirect count of 5
|
||||
$max = isset($params[self::MAX_REDIRECTS]) ? $params[self::MAX_REDIRECTS] : $this->defaultMaxRedirects;
|
||||
|
||||
// Throw an exception if the redirect count is exceeded
|
||||
if ($current > $max) {
|
||||
$this->throwTooManyRedirectsException($original, $max);
|
||||
return false;
|
||||
} else {
|
||||
// Create a redirect request based on the redirect rules set on the request
|
||||
return $this->createRedirectRequest(
|
||||
$request,
|
||||
$response->getStatusCode(),
|
||||
trim($response->getLocation()),
|
||||
$original
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a redirect request and handle any errors
|
||||
*
|
||||
* @param RequestInterface $original The originating request
|
||||
* @param RequestInterface $request The current request being redirected
|
||||
* @param Response $response The response of the current request
|
||||
*
|
||||
* @throws BadResponseException|\Exception
|
||||
*/
|
||||
protected function sendRedirectRequest(RequestInterface $original, RequestInterface $request, Response $response)
|
||||
{
|
||||
// Validate and create a redirect request based on the original request and current response
|
||||
if ($redirectRequest = $this->prepareRedirection($original, $request, $response)) {
|
||||
try {
|
||||
$redirectRequest->send();
|
||||
} catch (BadResponseException $e) {
|
||||
$e->getResponse();
|
||||
if (!$e->getResponse()) {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw a too many redirects exception for a request
|
||||
*
|
||||
* @param RequestInterface $original Request
|
||||
* @param int $max Max allowed redirects
|
||||
*
|
||||
* @throws TooManyRedirectsException when too many redirects have been issued
|
||||
*/
|
||||
protected function throwTooManyRedirectsException(RequestInterface $original, $max)
|
||||
{
|
||||
$original->getEventDispatcher()->addListener(
|
||||
'request.complete',
|
||||
$func = function ($e) use (&$func, $original, $max) {
|
||||
$original->getEventDispatcher()->removeListener('request.complete', $func);
|
||||
$str = "{$max} redirects were issued for this request:\n" . $e['request']->getRawHeaders();
|
||||
throw new TooManyRedirectsException($str);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
47961e7ef15667c93cd99be01b51f00a
|
|
@ -1,157 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Http;
|
||||
|
||||
use Guzzle\Http\Client;
|
||||
use Guzzle\Http\ClientInterface;
|
||||
use Guzzle\Stream\StreamRequestFactoryInterface;
|
||||
use Guzzle\Stream\PhpStreamRequestFactory;
|
||||
|
||||
/**
|
||||
* Simplified interface to Guzzle that does not require a class to be instantiated
|
||||
*/
|
||||
final class StaticClient
|
||||
{
|
||||
/** @var Client Guzzle client */
|
||||
private static $client;
|
||||
|
||||
/**
|
||||
* Mount the client to a simpler class name for a specific client
|
||||
*
|
||||
* @param string $className Class name to use to mount
|
||||
* @param ClientInterface $client Client used to send requests
|
||||
*/
|
||||
public static function mount($className = 'Guzzle', ClientInterface $client = null)
|
||||
{
|
||||
class_alias(__CLASS__, $className);
|
||||
if ($client) {
|
||||
self::$client = $client;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $method HTTP request method (GET, POST, HEAD, DELETE, PUT, etc)
|
||||
* @param string $url URL of the request
|
||||
* @param array $options Options to use with the request. See: Guzzle\Http\Message\RequestFactory::applyOptions()
|
||||
* @return \Guzzle\Http\Message\Response|\Guzzle\Stream\Stream
|
||||
*/
|
||||
public static function request($method, $url, $options = array())
|
||||
{
|
||||
// @codeCoverageIgnoreStart
|
||||
if (!self::$client) {
|
||||
self::$client = new Client();
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
$request = self::$client->createRequest($method, $url, null, null, $options);
|
||||
|
||||
if (isset($options['stream'])) {
|
||||
if ($options['stream'] instanceof StreamRequestFactoryInterface) {
|
||||
return $options['stream']->fromRequest($request);
|
||||
} elseif ($options['stream'] == true) {
|
||||
$streamFactory = new PhpStreamRequestFactory();
|
||||
return $streamFactory->fromRequest($request);
|
||||
}
|
||||
}
|
||||
|
||||
return $request->send();
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a GET request
|
||||
*
|
||||
* @param string $url URL of the request
|
||||
* @param array $options Array of request options
|
||||
*
|
||||
* @return \Guzzle\Http\Message\Response
|
||||
* @see Guzzle::request for a list of available options
|
||||
*/
|
||||
public static function get($url, $options = array())
|
||||
{
|
||||
return self::request('GET', $url, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a HEAD request
|
||||
*
|
||||
* @param string $url URL of the request
|
||||
* @param array $options Array of request options
|
||||
*
|
||||
* @return \Guzzle\Http\Message\Response
|
||||
* @see Guzzle::request for a list of available options
|
||||
*/
|
||||
public static function head($url, $options = array())
|
||||
{
|
||||
return self::request('HEAD', $url, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a DELETE request
|
||||
*
|
||||
* @param string $url URL of the request
|
||||
* @param array $options Array of request options
|
||||
*
|
||||
* @return \Guzzle\Http\Message\Response
|
||||
* @see Guzzle::request for a list of available options
|
||||
*/
|
||||
public static function delete($url, $options = array())
|
||||
{
|
||||
return self::request('DELETE', $url, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a POST request
|
||||
*
|
||||
* @param string $url URL of the request
|
||||
* @param array $options Array of request options
|
||||
*
|
||||
* @return \Guzzle\Http\Message\Response
|
||||
* @see Guzzle::request for a list of available options
|
||||
*/
|
||||
public static function post($url, $options = array())
|
||||
{
|
||||
return self::request('POST', $url, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a PUT request
|
||||
*
|
||||
* @param string $url URL of the request
|
||||
* @param array $options Array of request options
|
||||
*
|
||||
* @return \Guzzle\Http\Message\Response
|
||||
* @see Guzzle::request for a list of available options
|
||||
*/
|
||||
public static function put($url, $options = array())
|
||||
{
|
||||
return self::request('PUT', $url, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a PATCH request
|
||||
*
|
||||
* @param string $url URL of the request
|
||||
* @param array $options Array of request options
|
||||
*
|
||||
* @return \Guzzle\Http\Message\Response
|
||||
* @see Guzzle::request for a list of available options
|
||||
*/
|
||||
public static function patch($url, $options = array())
|
||||
{
|
||||
return self::request('PATCH', $url, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an OPTIONS request
|
||||
*
|
||||
* @param string $url URL of the request
|
||||
* @param array $options Array of request options
|
||||
*
|
||||
* @return \Guzzle\Http\Message\Response
|
||||
* @see Guzzle::request for a list of available options
|
||||
*/
|
||||
public static function options($url, $options = array())
|
||||
{
|
||||
return self::request('OPTIONS', $url, $options);
|
||||
}
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
{
|
||||
"name": "guzzle/http",
|
||||
"description": "HTTP libraries used by Guzzle",
|
||||
"homepage": "http://guzzlephp.org/",
|
||||
"keywords": ["http client", "http", "client", "Guzzle", "curl"],
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Michael Dowling",
|
||||
"email": "mtdowling@gmail.com",
|
||||
"homepage": "https://github.com/mtdowling"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.3.2",
|
||||
"guzzle/common": "self.version",
|
||||
"guzzle/parser": "self.version",
|
||||
"guzzle/stream": "self.version"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-curl": "*"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": { "Guzzle\\Http": "" }
|
||||
},
|
||||
"target-dir": "Guzzle/Http",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.7-dev"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,86 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Parser\Cookie;
|
||||
|
||||
/**
|
||||
* Default Guzzle implementation of a Cookie parser
|
||||
*/
|
||||
class CookieParser implements CookieParserInterface
|
||||
{
|
||||
/** @var array Cookie part names to snake_case array values */
|
||||
protected static $cookieParts = array(
|
||||
'domain' => 'Domain',
|
||||
'path' => 'Path',
|
||||
'max_age' => 'Max-Age',
|
||||
'expires' => 'Expires',
|
||||
'version' => 'Version',
|
||||
'secure' => 'Secure',
|
||||
'port' => 'Port',
|
||||
'discard' => 'Discard',
|
||||
'comment' => 'Comment',
|
||||
'comment_url' => 'Comment-Url',
|
||||
'http_only' => 'HttpOnly'
|
||||
);
|
||||
|
||||
public function parseCookie($cookie, $host = null, $path = null, $decode = false)
|
||||
{
|
||||
// Explode the cookie string using a series of semicolons
|
||||
$pieces = array_filter(array_map('trim', explode(';', $cookie)));
|
||||
|
||||
// The name of the cookie (first kvp) must include an equal sign.
|
||||
if (empty($pieces) || !strpos($pieces[0], '=')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create the default return array
|
||||
$data = array_merge(array_fill_keys(array_keys(self::$cookieParts), null), array(
|
||||
'cookies' => array(),
|
||||
'data' => array(),
|
||||
'path' => $path ?: '/',
|
||||
'http_only' => false,
|
||||
'discard' => false,
|
||||
'domain' => $host
|
||||
));
|
||||
$foundNonCookies = 0;
|
||||
|
||||
// Add the cookie pieces into the parsed data array
|
||||
foreach ($pieces as $part) {
|
||||
|
||||
$cookieParts = explode('=', $part, 2);
|
||||
$key = trim($cookieParts[0]);
|
||||
|
||||
if (count($cookieParts) == 1) {
|
||||
// Can be a single value (e.g. secure, httpOnly)
|
||||
$value = true;
|
||||
} else {
|
||||
// Be sure to strip wrapping quotes
|
||||
$value = trim($cookieParts[1], " \n\r\t\0\x0B\"");
|
||||
if ($decode) {
|
||||
$value = urldecode($value);
|
||||
}
|
||||
}
|
||||
|
||||
// Only check for non-cookies when cookies have been found
|
||||
if (!empty($data['cookies'])) {
|
||||
foreach (self::$cookieParts as $mapValue => $search) {
|
||||
if (!strcasecmp($search, $key)) {
|
||||
$data[$mapValue] = $mapValue == 'port' ? array_map('trim', explode(',', $value)) : $value;
|
||||
$foundNonCookies++;
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If cookies have not yet been retrieved, or this value was not found in the pieces array, treat it as a
|
||||
// cookie. IF non-cookies have been parsed, then this isn't a cookie, it's cookie data. Cookies then data.
|
||||
$data[$foundNonCookies ? 'data' : 'cookies'][$key] = $value;
|
||||
}
|
||||
|
||||
// Calculate the expires date
|
||||
if (!$data['expires'] && $data['max_age']) {
|
||||
$data['expires'] = time() + (int) $data['max_age'];
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Parser\Cookie;
|
||||
|
||||
/**
|
||||
* Cookie parser interface
|
||||
*/
|
||||
interface CookieParserInterface
|
||||
{
|
||||
/**
|
||||
* Parse a cookie string as set in a Set-Cookie HTTP header and return an associative array of data.
|
||||
*
|
||||
* @param string $cookie Cookie header value to parse
|
||||
* @param string $host Host of an associated request
|
||||
* @param string $path Path of an associated request
|
||||
* @param bool $decode Set to TRUE to urldecode cookie values
|
||||
*
|
||||
* @return array|bool Returns FALSE on failure or returns an array of arrays, with each of the sub arrays including:
|
||||
* - domain (string) - Domain of the cookie
|
||||
* - path (string) - Path of the cookie
|
||||
* - cookies (array) - Associative array of cookie names and values
|
||||
* - max_age (int) - Lifetime of the cookie in seconds
|
||||
* - version (int) - Version of the cookie specification. RFC 2965 is 1
|
||||
* - secure (bool) - Whether or not this is a secure cookie
|
||||
* - discard (bool) - Whether or not this is a discardable cookie
|
||||
* - custom (string) - Custom cookie data array
|
||||
* - comment (string) - How the cookie is intended to be used
|
||||
* - comment_url (str)- URL that contains info on how it will be used
|
||||
* - port (array|str) - Array of ports or null
|
||||
* - http_only (bool) - HTTP only cookie
|
||||
*/
|
||||
public function parseCookie($cookie, $host = null, $path = null, $decode = false);
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Parser\Message;
|
||||
|
||||
/**
|
||||
* Implements shared message parsing functionality
|
||||
*/
|
||||
abstract class AbstractMessageParser implements MessageParserInterface
|
||||
{
|
||||
/**
|
||||
* Create URL parts from HTTP message parts
|
||||
*
|
||||
* @param string $requestUrl Associated URL
|
||||
* @param array $parts HTTP message parts
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getUrlPartsFromMessage($requestUrl, array $parts)
|
||||
{
|
||||
// Parse the URL information from the message
|
||||
$urlParts = array(
|
||||
'path' => $requestUrl,
|
||||
'scheme' => 'http'
|
||||
);
|
||||
|
||||
// Check for the Host header
|
||||
if (isset($parts['headers']['Host'])) {
|
||||
$urlParts['host'] = $parts['headers']['Host'];
|
||||
} elseif (isset($parts['headers']['host'])) {
|
||||
$urlParts['host'] = $parts['headers']['host'];
|
||||
} else {
|
||||
$urlParts['host'] = null;
|
||||
}
|
||||
|
||||
if (false === strpos($urlParts['host'], ':')) {
|
||||
$urlParts['port'] = '';
|
||||
} else {
|
||||
$hostParts = explode(':', $urlParts['host']);
|
||||
$urlParts['host'] = trim($hostParts[0]);
|
||||
$urlParts['port'] = (int) trim($hostParts[1]);
|
||||
if ($urlParts['port'] == 443) {
|
||||
$urlParts['scheme'] = 'https';
|
||||
}
|
||||
}
|
||||
|
||||
// Check if a query is present
|
||||
$path = $urlParts['path'];
|
||||
$qpos = strpos($path, '?');
|
||||
if ($qpos) {
|
||||
$urlParts['query'] = substr($path, $qpos + 1);
|
||||
$urlParts['path'] = substr($path, 0, $qpos);
|
||||
} else {
|
||||
$urlParts['query'] = '';
|
||||
}
|
||||
|
||||
return $urlParts;
|
||||
}
|
||||
}
|
|
@ -1,110 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Parser\Message;
|
||||
|
||||
/**
|
||||
* Default request and response parser used by Guzzle. Optimized for speed.
|
||||
*/
|
||||
class MessageParser extends AbstractMessageParser
|
||||
{
|
||||
public function parseRequest($message)
|
||||
{
|
||||
if (!$message) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$parts = $this->parseMessage($message);
|
||||
|
||||
// Parse the protocol and protocol version
|
||||
if (isset($parts['start_line'][2])) {
|
||||
$startParts = explode('/', $parts['start_line'][2]);
|
||||
$protocol = strtoupper($startParts[0]);
|
||||
$version = isset($startParts[1]) ? $startParts[1] : '1.1';
|
||||
} else {
|
||||
$protocol = 'HTTP';
|
||||
$version = '1.1';
|
||||
}
|
||||
|
||||
$parsed = array(
|
||||
'method' => strtoupper($parts['start_line'][0]),
|
||||
'protocol' => $protocol,
|
||||
'version' => $version,
|
||||
'headers' => $parts['headers'],
|
||||
'body' => $parts['body']
|
||||
);
|
||||
|
||||
$parsed['request_url'] = $this->getUrlPartsFromMessage($parts['start_line'][1], $parsed);
|
||||
|
||||
return $parsed;
|
||||
}
|
||||
|
||||
public function parseResponse($message)
|
||||
{
|
||||
if (!$message) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$parts = $this->parseMessage($message);
|
||||
list($protocol, $version) = explode('/', trim($parts['start_line'][0]));
|
||||
|
||||
return array(
|
||||
'protocol' => $protocol,
|
||||
'version' => $version,
|
||||
'code' => $parts['start_line'][1],
|
||||
'reason_phrase' => isset($parts['start_line'][2]) ? $parts['start_line'][2] : '',
|
||||
'headers' => $parts['headers'],
|
||||
'body' => $parts['body']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a message into parts
|
||||
*
|
||||
* @param string $message Message to parse
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function parseMessage($message)
|
||||
{
|
||||
$startLine = null;
|
||||
$headers = array();
|
||||
$body = '';
|
||||
|
||||
// Iterate over each line in the message, accounting for line endings
|
||||
$lines = preg_split('/(\\r?\\n)/', $message, -1, PREG_SPLIT_DELIM_CAPTURE);
|
||||
for ($i = 0, $totalLines = count($lines); $i < $totalLines; $i += 2) {
|
||||
|
||||
$line = $lines[$i];
|
||||
|
||||
// If two line breaks were encountered, then this is the end of body
|
||||
if (empty($line)) {
|
||||
if ($i < $totalLines - 1) {
|
||||
$body = implode('', array_slice($lines, $i + 2));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Parse message headers
|
||||
if (!$startLine) {
|
||||
$startLine = explode(' ', $line, 3);
|
||||
} elseif (strpos($line, ':')) {
|
||||
$parts = explode(':', $line, 2);
|
||||
$key = trim($parts[0]);
|
||||
$value = isset($parts[1]) ? trim($parts[1]) : '';
|
||||
if (!isset($headers[$key])) {
|
||||
$headers[$key] = $value;
|
||||
} elseif (!is_array($headers[$key])) {
|
||||
$headers[$key] = array($headers[$key], $value);
|
||||
} else {
|
||||
$headers[$key][] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return array(
|
||||
'start_line' => $startLine,
|
||||
'headers' => $headers,
|
||||
'body' => $body
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Parser\Message;
|
||||
|
||||
/**
|
||||
* HTTP message parser interface used to parse HTTP messages into an array
|
||||
*/
|
||||
interface MessageParserInterface
|
||||
{
|
||||
/**
|
||||
* Parse an HTTP request message into an associative array of parts.
|
||||
*
|
||||
* @param string $message HTTP request to parse
|
||||
*
|
||||
* @return array|bool Returns false if the message is invalid
|
||||
*/
|
||||
public function parseRequest($message);
|
||||
|
||||
/**
|
||||
* Parse an HTTP response message into an associative array of parts.
|
||||
*
|
||||
* @param string $message HTTP response to parse
|
||||
*
|
||||
* @return array|bool Returns false if the message is invalid
|
||||
*/
|
||||
public function parseResponse($message);
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Parser\Message;
|
||||
|
||||
/**
|
||||
* Pecl HTTP message parser
|
||||
*/
|
||||
class PeclHttpMessageParser extends AbstractMessageParser
|
||||
{
|
||||
public function parseRequest($message)
|
||||
{
|
||||
if (!$message) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$parts = http_parse_message($message);
|
||||
|
||||
$parsed = array(
|
||||
'method' => $parts->requestMethod,
|
||||
'protocol' => 'HTTP',
|
||||
'version' => number_format($parts->httpVersion, 1),
|
||||
'headers' => $parts->headers,
|
||||
'body' => $parts->body
|
||||
);
|
||||
|
||||
$parsed['request_url'] = $this->getUrlPartsFromMessage($parts->requestUrl, $parsed);
|
||||
|
||||
return $parsed;
|
||||
}
|
||||
|
||||
public function parseResponse($message)
|
||||
{
|
||||
if (!$message) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$parts = http_parse_message($message);
|
||||
|
||||
return array(
|
||||
'protocol' => 'HTTP',
|
||||
'version' => number_format($parts->httpVersion, 1),
|
||||
'code' => $parts->responseCode,
|
||||
'reason_phrase' => $parts->responseStatus,
|
||||
'headers' => $parts->headers,
|
||||
'body' => $parts->body
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Parser;
|
||||
|
||||
/**
|
||||
* Registry of parsers used by the application
|
||||
*/
|
||||
class ParserRegistry
|
||||
{
|
||||
/** @var ParserRegistry Singleton instance */
|
||||
protected static $instance;
|
||||
|
||||
/** @var array Array of parser instances */
|
||||
protected $instances = array();
|
||||
|
||||
/** @var array Mapping of parser name to default class */
|
||||
protected $mapping = array(
|
||||
'message' => 'Guzzle\\Parser\\Message\\MessageParser',
|
||||
'cookie' => 'Guzzle\\Parser\\Cookie\\CookieParser',
|
||||
'url' => 'Guzzle\\Parser\\Url\\UrlParser',
|
||||
'uri_template' => 'Guzzle\\Parser\\UriTemplate\\UriTemplate',
|
||||
);
|
||||
|
||||
/**
|
||||
* @return self
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public static function getInstance()
|
||||
{
|
||||
if (!self::$instance) {
|
||||
self::$instance = new static;
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
// Use the PECL URI template parser if available
|
||||
if (extension_loaded('uri_template')) {
|
||||
$this->mapping['uri_template'] = 'Guzzle\\Parser\\UriTemplate\\PeclUriTemplate';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a parser by name from an instance
|
||||
*
|
||||
* @param string $name Name of the parser to retrieve
|
||||
*
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function getParser($name)
|
||||
{
|
||||
if (!isset($this->instances[$name])) {
|
||||
if (!isset($this->mapping[$name])) {
|
||||
return null;
|
||||
}
|
||||
$class = $this->mapping[$name];
|
||||
$this->instances[$name] = new $class();
|
||||
}
|
||||
|
||||
return $this->instances[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a custom parser by name with the register
|
||||
*
|
||||
* @param string $name Name or handle of the parser to register
|
||||
* @param mixed $parser Instantiated parser to register
|
||||
*/
|
||||
public function registerParser($name, $parser)
|
||||
{
|
||||
$this->instances[$name] = $parser;
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Parser\UriTemplate;
|
||||
|
||||
use Guzzle\Common\Exception\RuntimeException;
|
||||
|
||||
/**
|
||||
* Expands URI templates using the uri_template pecl extension (pecl install uri_template-beta)
|
||||
*
|
||||
* @link http://pecl.php.net/package/uri_template
|
||||
* @link https://github.com/ioseb/uri-template
|
||||
*/
|
||||
class PeclUriTemplate implements UriTemplateInterface
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
if (!extension_loaded('uri_template')) {
|
||||
throw new RuntimeException('uri_template PECL extension must be installed to use PeclUriTemplate');
|
||||
}
|
||||
}
|
||||
|
||||
public function expand($template, array $variables)
|
||||
{
|
||||
return uri_template($template, $variables);
|
||||
}
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Parser\UriTemplate;
|
||||
|
||||
/**
|
||||
* Expands URI templates using an array of variables
|
||||
*
|
||||
* @link http://tools.ietf.org/html/rfc6570
|
||||
*/
|
||||
interface UriTemplateInterface
|
||||
{
|
||||
/**
|
||||
* Expand the URI template using the supplied variables
|
||||
*
|
||||
* @param string $template URI Template to expand
|
||||
* @param array $variables Variables to use with the expansion
|
||||
*
|
||||
* @return string Returns the expanded template
|
||||
*/
|
||||
public function expand($template, array $variables);
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Guzzle\Parser\Url;
|
||||
|
||||
use Guzzle\Common\Version;
|
||||
|
||||
/**
|
||||
* Parses URLs into parts using PHP's built-in parse_url() function
|
||||
* @deprecated Just use parse_url. UTF-8 characters should be percent encoded anyways.
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class UrlParser implements UrlParserInterface
|
||||
{
|
||||
/** @var bool Whether or not to work with UTF-8 strings */
|
||||
protected $utf8 = false;
|
||||
|
||||
/**
|
||||
* Set whether or not to attempt to handle UTF-8 strings (still WIP)
|
||||
*
|
||||
* @param bool $utf8 Set to TRUE to handle UTF string
|
||||
*/
|
||||
public function setUtf8Support($utf8)
|
||||
{
|
||||
$this->utf8 = $utf8;
|
||||
}
|
||||
|
||||
public function parseUrl($url)
|
||||
{
|
||||
Version::warn(__CLASS__ . ' is deprecated. Just use parse_url()');
|
||||
|
||||
static $defaults = array('scheme' => null, 'host' => null, 'path' => null, 'port' => null, 'query' => null,
|
||||
'user' => null, 'pass' => null, 'fragment' => null);
|
||||
|
||||
$parts = parse_url($url);
|
||||
|
||||
// Need to handle query parsing specially for UTF-8 requirements
|
||||
if ($this->utf8 && isset($parts['query'])) {
|
||||
$queryPos = strpos($url, '?');
|
||||
if (isset($parts['fragment'])) {
|
||||
$parts['query'] = substr($url, $queryPos + 1, strpos($url, '#') - $queryPos - 1);
|
||||
} else {
|
||||
$parts['query'] = substr($url, $queryPos + 1);
|
||||
}
|
||||
}
|
||||
|
||||
return $parts + $defaults;
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue