1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219: 220: 221: 222: 223: 224: 225: 226: 227: 228: 229: 230: 231: 232: 233: 234: 235: 236: 237: 238: 239: 240: 241: 242: 243: 244: 245: 246: 247: 248: 249: 250: 251: 252: 253: 254: 255: 256: 257: 258: 259: 260: 261: 262: 263: 264: 265: 266: 267: 268: 269: 270: 271: 272: 273: 274: 275: 276: 277: 278: 279: 280: 281: 282: 283: 284: 285: 286: 287: 288: 289: 290: 291: 292: 293: 294: 295: 296: 297: 298: 299: 300: 301: 302: 303: 304: 305: 306: 307: 308: 309: 310: 311: 312: 313: 314: 315: 316: 317: 318: 319: 320: 321: 322: 323: 324: 325: 326: 327: 328: 329: 330: 331: 332: 333: 334: 335: 336: 337: 338: 339: 340: 341: 342: 343: 344: 345: 346: 347: 348: 349: 350: 351: 352: 353: 354: 355: 356: 357: 358: 359: 360:
<?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;
class RequestFactory implements RequestFactoryInterface
{
protected static $instance;
protected $methods;
protected $requestClass = 'Guzzle\\Http\\Message\\Request';
protected $entityEnclosingRequestClass = 'Guzzle\\Http\\Message\\EntityEnclosingRequest';
public static function getInstance()
{
if (!static::$instance) {
static::$instance = new static();
}
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']);
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') {
$request = new $this->requestClass($method, $url, $headers);
if ($body) {
$type = gettype($body);
if ($type == 'string' || $type == 'resource' || $type == 'object') {
$request->setResponseBody($body);
}
}
} else {
$request = new $this->entityEnclosingRequestClass($method, $url, $headers);
if ($body || $body === '0') {
if (is_array($body) || $body instanceof Collection) {
foreach ($body as $key => $value) {
if (is_string($value) && substr($value, 0, 1) == '@') {
$request->addPostFile($key, $value);
unset($body[$key]);
}
}
$request->addPostFields($body);
} else {
$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;
}
public function cloneRequestWithMethod(RequestInterface $request, $method)
{
if ($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());
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)
{
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) {
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) {
$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 (is_array($listener) && $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)
{
if (defined('CURLOPT_TIMEOUT_MS')) {
$request->getCurlOptions()->set(CURLOPT_TIMEOUT_MS, $value * 1000);
} else {
$request->getCurlOptions()->set(CURLOPT_TIMEOUT, $value);
}
}
protected function visit_connect_timeout(RequestInterface $request, $value, $flags)
{
if (defined('CURLOPT_CONNECTTIMEOUT_MS')) {
$request->getCurlOptions()->set(CURLOPT_CONNECTTIMEOUT_MS, $value * 1000);
} else {
$request->getCurlOptions()->set(CURLOPT_CONNECTTIMEOUT, $value);
}
}
protected function visit_debug(RequestInterface $request, $value, $flags)
{
if ($value) {
$request->getCurlOptions()->set(CURLOPT_VERBOSE, true);
}
}
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);
}
}
}