Merge branch 'develop'

This commit is contained in:
Matt Butcher
2012-05-04 18:00:10 -05:00
8 changed files with 109 additions and 24 deletions

View File

@@ -260,6 +260,7 @@ class CDN {
* 'cdn_enabled' => 1 * 'cdn_enabled' => 1
* 'name' => 'I♡HPCloud' * 'name' => 'I♡HPCloud'
* 'x-cdn-uri' => 'http://hcf937838.cdn.aw1.hpcloud.net' * 'x-cdn-uri' => 'http://hcf937838.cdn.aw1.hpcloud.net'
* 'x-cdn-ssl-uri' => 'https://hcf937838.cdn.aw1.hpcloud.net'
* 'ttl' => 1234 * 'ttl' => 1234
* ), * ),
* array( * array(
@@ -267,6 +268,7 @@ class CDN {
* 'cdn_enabled' => 0 * 'cdn_enabled' => 0
* 'name' => 'HPCloud2' * 'name' => 'HPCloud2'
* 'x-cdn-uri' => 'http://hcf9abc38.cdn.aw1.hpcloud.net' * 'x-cdn-uri' => 'http://hcf9abc38.cdn.aw1.hpcloud.net'
* 'x-cdn-ssl-uri' => 'https://hcf937838.cdn.aw1.hpcloud.net'
* 'ttl' => 1234 * 'ttl' => 1234
* ), * ),
* ); * );

View File

@@ -236,7 +236,10 @@ class ObjectStorage {
// This is needed b/c of a bug in SOS that sometimes // This is needed b/c of a bug in SOS that sometimes
// returns disabled containers (DEVEX-1733). // returns disabled containers (DEVEX-1733).
if ($item['cdn_enabled'] == 1) { if ($item['cdn_enabled'] == 1) {
$buffer[$item['name']] = $item['x-cdn-uri']; $buffer[$item['name']] = array(
'url' => $item['x-cdn-uri'],
'sslUrl' => $item['x-cdn-ssl-uri'],
);
} }
} }
$this->cdnContainers = $buffer; $this->cdnContainers = $buffer;
@@ -254,13 +257,17 @@ class ObjectStorage {
* *
* @param string $containerName * @param string $containerName
* The name of the container. * The name of the container.
* @param boolean $ssl
* If this is TRUE (default), get the URL to the SSL CDN;
* otherwise get the URL to the plain HTTP CDN.
* @retval string * @retval string
* The URL to the CDN container, or NULL if no such * The URL to the CDN container, or NULL if no such
* URL is found. * URL is found.
*/ */
public function cdnUrl($containerName) { public function cdnUrl($containerName, $ssl = TRUE) {
if (!empty($this->cdnContainers[$containerName])) { if (!empty($this->cdnContainers[$containerName])) {
return $this->cdnContainers[$containerName]; $key = $ssl ? 'sslUrl' : 'url';
return $this->cdnContainers[$containerName][$key];
} }
} }
@@ -339,7 +346,8 @@ class ObjectStorage {
$containerList[$cname] = Container::newFromJSON($container, $this->token(), $this->url()); $containerList[$cname] = Container::newFromJSON($container, $this->token(), $this->url());
if (!empty($this->cdnContainers[$cname])) { if (!empty($this->cdnContainers[$cname])) {
$containerList[$cname]->useCDN($this->cdnContainers[$cname]); $cdnList = $this->cdnContainers[$cname];
$containerList[$cname]->useCDN($cdnList['url'], $cdnList['sslUrl']);
} }
} }
@@ -368,7 +376,8 @@ class ObjectStorage {
$container = Container::newFromResponse($name, $data, $this->token(), $this->url()); $container = Container::newFromResponse($name, $data, $this->token(), $this->url());
if (isset($this->cdnContainers[$name])) { if (isset($this->cdnContainers[$name])) {
$container->useCDN($this->cdnContainers[$name]); $cdnList = $this->cdnContainers[$name];
$container->useCDN($cdnList['url'], $cdnList['sslUrl']);
} }
return $container; return $container;

View File

@@ -95,6 +95,7 @@ class Container implements \Countable, \IteratorAggregate {
// This is only set if CDN service is activated. // This is only set if CDN service is activated.
protected $cdnUrl; protected $cdnUrl;
protected $cdnSslUrl;
/** /**
* Transform a metadata array into headers. * Transform a metadata array into headers.
@@ -335,9 +336,12 @@ class Container implements \Countable, \IteratorAggregate {
* *
* @param string $url * @param string $url
* The URL to the CDN for this container. * The URL to the CDN for this container.
* @param string $sslUrl
* The SSL URL to the CDN for this container.
*/ */
public function useCDN($url) { public function useCDN($url, $sslUrl) {
$this->cdnUrl = $url; $this->cdnUrl = $url;
$this->cdnSslUrl = $sslUrl;
} }
/** /**
@@ -681,13 +685,18 @@ class Container implements \Countable, \IteratorAggregate {
* *
* @param string $name * @param string $name
* The name of the object to load. * The name of the object to load.
* @param boolean $requireSSL
* If this is TRUE (the default), then SSL will always be
* used. If this is FALSE, then CDN-based fetching will
* use non-SSL, which is faster.
* @retval \HPCloud\Storage\ObjectStorage\RemoteObject * @retval \HPCloud\Storage\ObjectStorage\RemoteObject
* A remote object with the content already stored locally. * A remote object with the content already stored locally.
*/ */
public function object($name) { public function object($name, $requireSSL = TRUE) {
$url = self::objectUrl($this->url, $name); $url = self::objectUrl($this->url, $name);
$cdn = self::objectUrl($this->cdnUrl, $name); $cdn = self::objectUrl($this->cdnUrl, $name);
$cdnSsl = self::objectUrl($this->cdnSslUrl, $name);
$headers = array(); $headers = array();
// Auth token. // Auth token.
@@ -699,7 +708,9 @@ class Container implements \Countable, \IteratorAggregate {
$response = $client->doRequest($url, 'GET', $headers); $response = $client->doRequest($url, 'GET', $headers);
} }
else { else {
$response = $client->doRequest($cdn, 'GET', $headers); $from = $requireSSL ? $cdnSsl : $cdn;
// print "Fetching object from $from\n";
$response = $client->doRequest($from, 'GET', $headers);
} }
if ($response->status() != 200) { if ($response->status() != 200) {
@@ -710,7 +721,7 @@ class Container implements \Countable, \IteratorAggregate {
$remoteObject->setContent($response->content()); $remoteObject->setContent($response->content());
if (!empty($this->cdnUrl)) { if (!empty($this->cdnUrl)) {
$remoteObject->useCDN($cdn); $remoteObject->useCDN($cdn, $cdnSsl);
} }
return $remoteObject; return $remoteObject;
@@ -748,6 +759,7 @@ class Container implements \Countable, \IteratorAggregate {
public function proxyObject($name) { public function proxyObject($name) {
$url = self::objectUrl($this->url, $name); $url = self::objectUrl($this->url, $name);
$cdn = self::objectUrl($this->cdnUrl, $name); $cdn = self::objectUrl($this->cdnUrl, $name);
$cdnSsl = self::objectUrl($this->cdnSslUrl, $name);
$headers = array( $headers = array(
'X-Auth-Token' => $this->token, 'X-Auth-Token' => $this->token,
); );
@@ -759,7 +771,7 @@ class Container implements \Countable, \IteratorAggregate {
$response = $client->doRequest($url, 'HEAD', $headers); $response = $client->doRequest($url, 'HEAD', $headers);
} }
else { else {
$response = $client->doRequest($cdn, 'HEAD', $headers); $response = $client->doRequest($cdnSsl, 'HEAD', $headers);
} }
if ($response->status() != 200) { if ($response->status() != 200) {
@@ -771,7 +783,7 @@ class Container implements \Countable, \IteratorAggregate {
$obj = RemoteObject::newFromHeaders($name, $headers, $this->token, $url); $obj = RemoteObject::newFromHeaders($name, $headers, $this->token, $url);
if (!empty($this->cdnUrl)) { if (!empty($this->cdnUrl)) {
$obj->useCDN($cdn); $obj->useCDN($cdn, $cdnSsl);
} }
return $obj; return $obj;
@@ -944,8 +956,8 @@ class Container implements \Countable, \IteratorAggregate {
return $this->url; return $this->url;
} }
public function cdnUrl() { public function cdnUrl($ssl = TRUE) {
return $this->cdnUrl; return $ssl ? $this->cdnSslUrl : $this->cdnUrl;
} }
/** /**

View File

@@ -68,6 +68,7 @@ class RemoteObject extends Object {
protected $allHeaders; protected $allHeaders;
protected $cdnUrl; protected $cdnUrl;
protected $cdnSslUrl;
/** /**
* Create a new RemoteObject from JSON data. * Create a new RemoteObject from JSON data.
@@ -118,8 +119,10 @@ class RemoteObject extends Object {
* subsequent requests. If this is set, this object may use * subsequent requests. If this is set, this object may use
* CDN to make subsequent requests. It may also return the * CDN to make subsequent requests. It may also return the
* CDN URL when requested. * CDN URL when requested.
* @param string $cdnSslUrl
* The URL to the SSL-protected CDN version of the object.
*/ */
public static function newFromHeaders($name, $headers, $token, $url, $cdnUrl = NULL) { public static function newFromHeaders($name, $headers, $token, $url, $cdnUrl = NULL, $cdnSslUrl = NULL) {
$object = new RemoteObject($name); $object = new RemoteObject($name);
$object->allHeaders = $headers; $object->allHeaders = $headers;
@@ -153,6 +156,7 @@ class RemoteObject extends Object {
$object->token = $token; $object->token = $token;
$object->url = $url; $object->url = $url;
$object->cdnUrl = $cdnUrl; $object->cdnUrl = $cdnUrl;
$object->cdnSslUrl = $cdnSslUrl;
return $object; return $object;
} }
@@ -176,9 +180,12 @@ class RemoteObject extends Object {
* *
* @param string $url * @param string $url
* The URL to this object in CDN. * The URL to this object in CDN.
* @param string $sslUrl
* The SSL URL to this object in CDN.
*/ */
public function useCDN($url) { public function useCDN($url, $sslUrl) {
$this->cdnUrl = $url; $this->cdnUrl = $url;
$this->cdnSslUrl = $sslUrl;
} }
/** /**
@@ -196,6 +203,11 @@ class RemoteObject extends Object {
* object. See ObjectStorage::useCDN(), Container::useCDN() and * object. See ObjectStorage::useCDN(), Container::useCDN() and
* RemoteObject::useCDN(). (Generally, using ObjectStorage::useCDN() * RemoteObject::useCDN(). (Generally, using ObjectStorage::useCDN()
* is all you need to do.) * is all you need to do.)
* @param boolean $useSSL
* FOR CACHED URLS ONLY, there is an option for either SSL or non-SSL
* URLs. By default, we use SSL URLs because (a) it's safer, and
* (b) it mirrors non-CDN behavior. This can be turned off by setting
* $useSSL to FALSE.
* @retval string * @retval string
* A URL to the object. The following considerations apply: * A URL to the object. The following considerations apply:
* - If the container is public, this URL can be loaded without * - If the container is public, this URL can be loaded without
@@ -207,10 +219,10 @@ class RemoteObject extends Object {
* - If this object has never been saved remotely, then there will be * - If this object has never been saved remotely, then there will be
* no URL, and this will return NULL. * no URL, and this will return NULL.
*/ */
public function url($cached = FALSE) { public function url($cached = FALSE, $useSSL = TRUE) {
if ($cached && !empty($this->cdnUrl)) { if ($cached && !empty($this->cdnUrl)) {
return $this->cdnUrl; return $useSSL ? $this->cdnSslUrl : $this->cdnUrl;
} }
return $this->url; return $this->url;
} }

View File

@@ -248,6 +248,9 @@ use \HPCloud\Storage\ObjectStorage;
* - The container must have CDN enabled * - The container must have CDN enabled
* - The CDN container must be active ("cdn-enabled") * - The CDN container must be active ("cdn-enabled")
* - Authentication info must be accessible to the stream wrapper. * - Authentication info must be accessible to the stream wrapper.
* - cdn_require_ssl: If this is set to FALSE, then CDN-based requests
* may use plain HTTP instead of HTTPS. This will spead up CDN
* fetches at the cost of security.
* *
* @attention * @attention
* ADVANCED: You can also pass an HPCloud::Storage::CDN object in use_cdn instead of * ADVANCED: You can also pass an HPCloud::Storage::CDN object in use_cdn instead of
@@ -827,14 +830,16 @@ class StreamWrapper {
// EXPERIMENTAL: // EXPERIMENTAL:
// If we can get the resource from CDN, we do so now. Note that we try to sidestep // If we can get the resource from CDN, we do so now. Note that we try to sidestep
// the Container creation, which saves us an HTTP request. // the Container creation, which saves us an HTTP request.
$cdnUrl = $this->store->cdnUrl($containerName); $cdnUrl = $this->store->cdnUrl($containerName, FALSE);
$cdnSslUrl = $this->store->cdnUrl($containerName, TRUE);
if (!empty($cdnUrl) && !$this->isWriting && !$this->isAppending) { if (!empty($cdnUrl) && !$this->isWriting && !$this->isAppending) {
$requireSSL = (boolean) $this->cxt('cdn_require_ssl', TRUE);
try { try {
$newUrl = $this->store->url() . '/' . $containerName; $newUrl = $this->store->url() . '/' . $containerName;
$token = $this->store->token(); $token = $this->store->token();
$this->container = new \HPCloud\Storage\ObjectStorage\Container($containerName, $newUrl, $token); $this->container = new \HPCloud\Storage\ObjectStorage\Container($containerName, $newUrl, $token);
$this->container->useCDN($cdnUrl); $this->container->useCDN($cdnUrl, $cdnSslUrl);
$this->obj = $this->container->object($objectName); $this->obj = $this->container->object($objectName, $requireSSL);
$this->objStream = $this->obj->stream(); $this->objStream = $this->obj->stream();
return TRUE; return TRUE;
@@ -1569,6 +1574,9 @@ class StreamWrapper {
* When use_cdn is set to TRUE, the wrapper tries to use CDN service. * When use_cdn is set to TRUE, the wrapper tries to use CDN service.
* In such cases, we need a handle to the CDN object. This initializes * In such cases, we need a handle to the CDN object. This initializes
* that handle, which can later be used to get other information. * that handle, which can later be used to get other information.
*
* Also note that CDN's default behavior is to fetch over SSL CDN.
* To disable this, set 'cdn_require_ssl' to FALSE.
*/ */
protected function initializeCDN($token, $catalog) { protected function initializeCDN($token, $catalog) {
$cdn = $this->cxt('use_cdn', FALSE); $cdn = $this->cxt('use_cdn', FALSE);

View File

@@ -95,7 +95,7 @@ else {
} }
if (empty($token)) { if (empty($token)) {
print "Authentication seemed to succeed, but no token was return." . PHP_EOL; print "Authentication seemed to succeed, but no token was returned." . PHP_EOL;
exit(1); exit(1);
} }

View File

@@ -66,20 +66,39 @@ print "***** TESTING CDN ENABLED" . PHP_EOL;
if ($cdnData['cdn_enabled'] != 1) { if ($cdnData['cdn_enabled'] != 1) {
die('Cannot test CDN: You must enable CDN on ' . $cname); die('Cannot test CDN: You must enable CDN on ' . $cname);
} }
$container = $objstore->container($cname); $container = $objstore->container($cname);
print "***** TESTING CDN URL" . PHP_EOL; print "***** TESTING CDN URL" . PHP_EOL;
$cdnSsl = $objstore->cdnUrl($cname);
$cdnPlain = $objstore->cdnUrl($cname, FALSE);
if ($cdnSsl == $cdnPlain) {
die(sprintf("Surprise! %s matches %s\n", $cdnSsl, $cdnPlain));
}
print 'SSL CDN: ' . $cdnSsl. PHP_EOL;
print 'Plain CDN: ' . $cdnPlain . PHP_EOL;
print 'Container CDN URL: ' . $container->cdnUrl() . PHP_EOL;
if ($container->cdnUrl() == NULL) { if ($container->cdnUrl() == NULL) {
die('No CDN URL for Container ' . $cname); die('No CDN URL for Container ' . $cname);
} }
if ($cdnSsl != $container->cdnUrl()) {
die(sprintf("Expected SSL CDN %s to match Container CDN %s\n", $cdnSsl, $container->cdnUrl()));
}
$o = new \HPCloud\Storage\ObjectStorage\Object('CDNTest.txt', 'TEST'); $o = new \HPCloud\Storage\ObjectStorage\Object('CDNTest.txt', 'TEST');
$container->save($o); $container->save($o);
$copy = $container->object($o->name()); $copy = $container->object($o->name());
print "***** TESTING OBJECT CDN URLS." . PHP_EOL;
print "Object SSL URL: " . $copy->url() . PHP_EOL;
print "Object CDN SSL URL: " . $copy->url(TRUE) . PHP_EOL;
print "Object CDN URL: " . $copy->url(TRUE, FALSE) . PHP_EOL;
if ($copy->url(TRUE) == $copy->url(TRUE, FALSE)) {
die(sprintf("Object SSL URL %s should not match non-SSL URL %s\n", $copy->url(TRUE), $copy->url(TRUE, FALSE)));
}
print "***** TESTING THAT CDN WAS USED." . PHP_EOL; print "***** TESTING THAT CDN WAS USED." . PHP_EOL;
if ($copy->url() == $copy->url(TRUE)) { if ($copy->url() == $copy->url(TRUE)) {
die('Object Storage not used for ' . $o->name()); die('Object Storage not used for ' . $o->name());
@@ -96,8 +115,31 @@ $cxt = stream_context_create(array(
'use_cdn' => TRUE, 'use_cdn' => TRUE,
), ),
)); ));
$cxt2 = stream_context_create(array(
'swift' => array(
//'token' => $token,
'tenantid' => $ini['hpcloud.identity.tenantId'],
'account' => $ini['hpcloud.identity.account'],
'key' => $ini['hpcloud.identity.secret'],
'endpoint' => $ini['hpcloud.identity.url'],
'use_cdn' => TRUE,
'cdn_require_ssl' => FALSE,
),
));
print "***** TESTING RETURNED DATA" . PHP_EOL; print "***** TESTING RETURNED DATA" . PHP_EOL;
print file_get_contents('swift://' . TEST_CONTAINER . '/CDNTest.txt', FALSE, $cxt); $res = array(
'internal' => file_get_contents('swift://' . TEST_CONTAINER . '/CDNTest.txt', FALSE, $cxt),
'internalNoSSL' => file_get_contents('swift://' . TEST_CONTAINER . '/CDNTest.txt', FALSE, $cxt2),
'external' => file_get_contents($copy->url()),
'externalSslCdn' => file_get_contents($copy->url(TRUE)),
'externalCdn' => file_get_contents($copy->url(TRUE, FALSE)),
);
foreach ($res as $name => $val) {
if ($val != 'TEST') {
die(sprintf("Facility %s failed, returning '%s' instead of TEST.", $name, $val));
}
}
print PHP_EOL . "***** All tests passed." . PHP_EOL; print PHP_EOL . "***** All tests passed." . PHP_EOL;

View File

@@ -28,7 +28,7 @@ hpcloud.identity.password =
; For authentication by account ID. ; For authentication by account ID.
hpcloud.identity.account = hpcloud.identity.account =
hpcloud.identity.key = hpcloud.identity.secret =
;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Configuration Parameters ; ; Configuration Parameters ;