From c8d7183187e86ac7fdbe7bbaa4310312cdf9ac0e Mon Sep 17 00:00:00 2001 From: Michael Dowling Date: Sun, 3 Mar 2013 20:04:06 -0800 Subject: [PATCH] Adding a way to create PHP streams based on request objects --- src/Guzzle/Stream/PhpStreamRequestFactory.php | 163 ++++++++++++++++++ .../Stream/StreamRequestFactoryInterface.php | 22 +++ src/Guzzle/Stream/composer.json | 3 +- 3 files changed, 187 insertions(+), 1 deletion(-) create mode 100644 src/Guzzle/Stream/PhpStreamRequestFactory.php create mode 100644 src/Guzzle/Stream/StreamRequestFactoryInterface.php diff --git a/src/Guzzle/Stream/PhpStreamRequestFactory.php b/src/Guzzle/Stream/PhpStreamRequestFactory.php new file mode 100644 index 00000000..bfb806ac --- /dev/null +++ b/src/Guzzle/Stream/PhpStreamRequestFactory.php @@ -0,0 +1,163 @@ +createDefaultContext($request); + + // Use the request's URL + $this->setUrl($request); + + // Add SSL options if needed + if ($request->getScheme() == 'https') { + $this->addSslOptions($request); + } + + // Add the content for the request if needed + if ($request instanceof EntityEnclosingRequestInterface) { + $this->addBodyOptions($request); + } + + // Merge in custom context options + if ($contextOptions) { + $this->mergeContextOptions($contextOptions); + } + + // Create the file handle but silence errors + return $this->createStream(); + } + + /** + * Adds the default context options to the stream context options + * + * @param RequestInterface $request Request + */ + protected function createDefaultContext(RequestInterface $request) + { + $this->context = array( + 'http' => array( + 'method' => $request->getMethod(), + 'header' => $request->getHeaderLines(), + 'protocol_version' => '1.0', + 'ignore_errors' => '1' + ) + ); + } + + /** + * Set the URL to use with the factory + * + * @param RequestInterface $request Request that owns the URL + */ + protected function setUrl(RequestInterface $request) + { + $this->url = $request->getUrl(true); + + // Check for basic Auth username + if ($request->getUsername()) { + $this->url->setUsername($request->getUsername()); + } + + // Check for basic Auth password + if ($request->getPassword()) { + $this->url->setPassword($request->getPassword()); + } + } + + /** + * Add SSL options to the stream context + * + * @param RequestInterface $request Request + */ + protected function addSslOptions(RequestInterface $request) + { + if ($verify = $request->getCurlOptions()->get(CURLOPT_SSL_VERIFYPEER)) { + $this->context['ssl']['verify_peer'] = true; + } + + if ($cafile = $request->getCurlOptions()->get(CURLOPT_CAINFO)) { + $this->context['ssl']['cafile'] = $cafile; + } + } + + /** + * Add body (content) specific options to the context options + * + * @param EntityEnclosingRequestInterface $request + */ + protected function addBodyOptions(EntityEnclosingRequestInterface $request) + { + if ($request->getPostFields()) { + $this->context['http']['content'] = (string) $request->getPostFields(); + } elseif ($request->getBody()) { + $this->context['http']['content'] = (string) $request->getBody(); + } + if ($this->context['http']['content']) { + $this->context['http']['header'][] = 'Content-Length: ' . strlen($this->context['http']['content']); + } + } + + /** + * Merge custom context options into the default context options + * + * @param array $contextOptions Context options + */ + protected function mergeContextOptions(array $contextOptions) + { + foreach ($contextOptions as $wrapper => $options) { + if (!isset($this->context[$wrapper])) { + $this->context[$wrapper] = array(); + } + if (is_array($options)) { + foreach ($options as $optionName => $optionValue) { + $this->context[$wrapper][$optionName] = $optionValue; + } + } + } + } + + /** + * Create the stream for the request with the context options + * + * @return resource + * @throws RuntimeException If an error occurs + */ + protected function createStream() + { + $level = error_reporting(0); + $fp = fopen((string) $this->url, 'r', false, stream_context_create($this->context)); + error_reporting($level); + if (false === $fp) { + // If the file could not be created, then grab the last error and throw an exception + $error = error_get_last(); + throw new RuntimeException($error['message']); + } + + return $fp; + } +} diff --git a/src/Guzzle/Stream/StreamRequestFactoryInterface.php b/src/Guzzle/Stream/StreamRequestFactoryInterface.php new file mode 100644 index 00000000..7b51e408 --- /dev/null +++ b/src/Guzzle/Stream/StreamRequestFactoryInterface.php @@ -0,0 +1,22 @@ +=5.3.2", - "guzzle/common": "self.version" + "guzzle/common": "self.version", + "guzzle/http": "self.version" }, "autoload": { "psr-0": { "Guzzle\\Stream": "" }