You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@shindig.apache.org by ch...@apache.org on 2009/02/17 12:53:06 UTC
svn commit: r744970 - in /incubator/shindig/trunk/php/src: common/
common/sample/ gadgets/
Author: chabotc
Date: Tue Feb 17 11:53:06 2009
New Revision: 744970
URL: http://svn.apache.org/viewvc?rev=744970&view=rev
Log:
Changed the caching expiration policy from a expiration on get to a TTL on set, and modified the RemoteContent fetchers to use the Cache-Control: max-age or Expiration headers to determine the TTL for caching them
Modified:
incubator/shindig/trunk/php/src/common/Cache.php
incubator/shindig/trunk/php/src/common/RemoteContent.php
incubator/shindig/trunk/php/src/common/RemoteContentFetcher.php
incubator/shindig/trunk/php/src/common/RemoteContentRequest.php
incubator/shindig/trunk/php/src/common/sample/BasicRemoteContent.php
incubator/shindig/trunk/php/src/common/sample/BasicRemoteContentFetcher.php
incubator/shindig/trunk/php/src/common/sample/CacheApc.php
incubator/shindig/trunk/php/src/common/sample/CacheFile.php
incubator/shindig/trunk/php/src/common/sample/CacheMemcache.php
incubator/shindig/trunk/php/src/gadgets/SigningFetcher.php
Modified: incubator/shindig/trunk/php/src/common/Cache.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/common/Cache.php?rev=744970&r1=744969&r2=744970&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/common/Cache.php (original)
+++ incubator/shindig/trunk/php/src/common/Cache.php Tue Feb 17 11:53:06 2009
@@ -24,9 +24,9 @@
abstract class Cache {
- abstract function get($key, $expiration = false);
+ abstract function get($key);
- abstract function set($key, $value);
+ abstract function set($key, $value, $ttl = false);
abstract function delete($key);
}
\ No newline at end of file
Modified: incubator/shindig/trunk/php/src/common/RemoteContent.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/common/RemoteContent.php?rev=744970&r1=744969&r2=744970&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/common/RemoteContent.php (original)
+++ incubator/shindig/trunk/php/src/common/RemoteContent.php Tue Feb 17 11:53:06 2009
@@ -21,8 +21,8 @@
/*
* remoteContent* classes, we departed from the shindig java base style a bit here
- * We want to use curl_multi for our content fetching because we don't have any fancy
- * worker queue's where the java variant does.
+ * We want to use curl_multi for our content fetching because we don't have any fancy
+ * worker queue's where the java variant does.
* So a different methodlogy which calls for a different working unfortunatly, however
* it's kept in the spirit of the java variant as much as possible
*/
@@ -32,7 +32,7 @@
abstract class RemoteContent {
- abstract public function fetch($request, $context);
+ abstract public function fetch(RemoteContentRequest $request, $context);
abstract public function multiFetch(Array $requests, Array $contexts);
}
Modified: incubator/shindig/trunk/php/src/common/RemoteContentFetcher.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/common/RemoteContentFetcher.php?rev=744970&r1=744969&r2=744970&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/common/RemoteContentFetcher.php (original)
+++ incubator/shindig/trunk/php/src/common/RemoteContentFetcher.php Tue Feb 17 11:53:06 2009
@@ -20,14 +20,14 @@
abstract class RemoteContentFetcher {
-
+
protected $fetcher;
protected function setNextFetcher($fetcher = null) {
$this->fetcher = $fetcher;
}
- abstract public function fetchRequest($request);
+ abstract public function fetchRequest(RemoteContentRequest $request);
abstract public function multiFetchRequest(Array $requests);
Modified: incubator/shindig/trunk/php/src/common/RemoteContentRequest.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/common/RemoteContentRequest.php?rev=744970&r1=744969&r2=744970&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/common/RemoteContentRequest.php (original)
+++ incubator/shindig/trunk/php/src/common/RemoteContentRequest.php Tue Feb 17 11:53:06 2009
@@ -67,7 +67,7 @@
}
// Bypass caching in proxies as well.
if (! $setPragmaHeader && $options->ignoreCache) {
- $tmpHeaders .= "Pragma:no-cache\n";
+ $tmpHeaders .= "Pragma: no-cache\n";
}
$this->headers = $tmpHeaders;
}
@@ -85,22 +85,6 @@
}
/**
- * Creates a new request to a different URL using all request data from
- * an existing request.
- *
- * @param uri
- * @param base The base request to copy data from.
- */
- public static function createRemoteContentRequestWithUriBase($uri, $base) {
- $this->uri = $uri;
- $this->method = $base->method;
- $this->options = $base->options;
- $this->headers = $base->headers;
- $this->contentType = $base->contentType;
- $this->postBody = $base->postBody;
- }
-
- /**
* Basic GET request.
*
* @param uri
@@ -110,75 +94,6 @@
}
/**
- * GET with options
- *
- * @param uri
- * @param options
- */
- public function createRemoteContentRequestWithUriOptions($uri, $options) {
- $this->createRemoteContentRequest("GET", $uri, null, null, $options);
- }
-
- /**
- * GET request with custom headers and default options
- * @param uri
- * @param headers
- */
- public function RemoteContentRequestWithUriHeaders($uri, $headers) {
- $this->createRemoteContentRequest("GET", $uri, $headers, null, RemoteContentRequest::getDefaultOptions());
- }
-
- /**
- * GET request with custom headers + options
- * @param uri
- * @param headers
- * @param options
- */
- public function createRemoteContentRequestWithUriHeadersOptions($uri, $headers, $options) {
- $this->createRemoteContentRequest("GET", $uri, $headers, null, $options);
- }
-
- /**
- * Basic POST request
- * @param uri
- * @param postBody
- */
- public function RemoteContentRequestWithUriPostBody($uri, $postBody) {
- $this->createRemoteContentRequest("POST", $uri, null, $postBody, RemoteContentRequest::getDefaultOptions());
- }
-
- /**
- * POST request with options
- * @param uri
- * @param postBody
- * @param options
- */
- public function createRemoteContentRequestWithUriPostBodyOptions($uri, $postBody, $options) {
- $this->createRemoteContentRequest("POST", $uri, null, $postBody, $options);
- }
-
- /**
- * POST request with headers
- * @param uri
- * @param headers
- * @param postBody
- */
- public function createRemoteContentRequestWithUriHeadersPostBody($uri, $headers, $postBody) {
- $this->createRemoteContentRequest("POST", $uri, $headers, $postBody, RemoteContentRequest::getDefaultOptions());
- }
-
- /**
- * POST request with options + headers
- * @param uri
- * @param headers
- * @param postBody
- * @param options
- */
- public function createRemoteContentRequestWithUriHeadersPostBodyOptions($uri, $headers, $postBody, $options) {
- $this->createRemoteContentRequest("POST", $uri, $headers, $postBody, $options);
- }
-
- /**
* Creates a simple GET request
*
* @param uri
@@ -190,23 +105,6 @@
return $this->createRemoteContentRequestWithUriOptions($uri, $options);
}
- /**
- * Simple constructor for setting a basic response from a string. Mostly used
- * for testing.
- *
- * @param body
- */
- public function getHttpFalseResponseBody($body) {
- return $this->createFalseResponse(RemoteContentRequest::$SC_OK, $body, null);
- }
-
- private function createFalseResponse($httpCode, $body, $headers) {
- $this->httpCode = $httpCode;
- $this->responseContent = $body;
- $this->headers = $headers;
- return $this;
- }
-
// returns a hash code which identifies this request, used for caching
// takes url and postbody into account for constructing the sha1 checksum
public function toHash() {
@@ -307,17 +205,8 @@
return null;
}
- //FIXME: Find a better way to do this
- // The headers can be an array of elements.
public function getResponseHeader($headerName) {
- $headers = explode("\n", $this->responseHeaders);
- foreach ($headers as $header) {
- $key = explode(":", $header, 2);
- if ($key[0] == $headerName) {
- return trim($key[1]);
- }
- }
- return null;
+ return isset($this->responseHeaders[$headerName]) ? $this->responseHeaders[$headerName] : null;
}
public function getCreated() {
Modified: incubator/shindig/trunk/php/src/common/sample/BasicRemoteContent.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/common/sample/BasicRemoteContent.php?rev=744970&r1=744969&r2=744970&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/common/sample/BasicRemoteContent.php (original)
+++ incubator/shindig/trunk/php/src/common/sample/BasicRemoteContent.php Tue Feb 17 11:53:06 2009
@@ -18,60 +18,78 @@
* under the License.
*/
-
class BasicRemoteContent extends RemoteContent {
- public function fetch($request, $context) {
+ public function fetch(RemoteContentRequest $request, $context) {
$cache = Config::get('data_cache');
$cache = new $cache();
$remoteContentFetcher = new BasicRemoteContentFetcher();
- if (! ($request instanceof RemoteContentRequest)) {
- throw new RemoteContentException("Invalid request type in remoteContent");
- }
- // determine which requests we can load from cache, and which we have to actually fetch
- if (! $context->getIgnoreCache() && ! $request->isPost() && ($cachedRequest = $cache->get($request->toHash(), $context->getRefreshInterval())) !== false) {
- $ret = $cachedRequest;
+ if (! $context->getIgnoreCache() && ! $request->isPost() && ($cachedRequest = $cache->get($request->toHash())) !== false) {
+ $request = $cachedRequest;
} else {
- $ret = $remoteContentFetcher->fetchRequest($request);
- // only cache requests that returned a 200 OK and is not a POST
- if ($request->getHttpCode() == '200' && ! $request->isPost()) {
- $cache->set($request->toHash(), $request);
- }
+ $request = $remoteContentFetcher->fetchRequest($request);
+ $this->setRequestCache($request, $cache, $context);
}
- return $ret;
+ return $request;
}
public function multiFetch(Array $requests, Array $contexts) {
$cache = Config::get('data_cache');
$cache = new $cache();
$remoteContentFetcher = new BasicRemoteContentFetcher();
-
$rets = array();
$requestsToProc = array();
-
foreach ($requests as $request) {
list(, $context) = each($contexts);
if (! ($request instanceof RemoteContentRequest)) {
throw new RemoteContentException("Invalid request type in remoteContent");
}
// determine which requests we can load from cache, and which we have to actually fetch
- if (! $context->getIgnoreCache() && ! $request->isPost() && ($cachedRequest = $cache->get($request->toHash(), $context->getRefreshInterval())) !== false) {
+ if (! $context->getIgnoreCache() && ! $request->isPost() && ($cachedRequest = $cache->get($request->toHash())) !== false) {
$rets[] = $cachedRequest;
} else {
$requestsToProc[] = $request;
}
}
-
$newRets = $remoteContentFetcher->multiFetchRequest($requestsToProc);
-
foreach ($newRets as $request) {
- // only cache requests that returned a 200 OK and is not a POST
- if ($request->getHttpCode() == '200' && ! $request->isPost()) {
- $cache->set($request->toHash(), $request);
- }
+ $this->setRequestCache($request, $cache, $context);
$rets[] = $request;
}
-
return $rets;
}
+
+ private function setRequestCache(RemoteContentRequest $request, Cache $cache, GadgetContext $context) {
+ if (! $request->isPost() && ! $context->getIgnoreCache()) {
+ $ttl = Config::get('cache_time');
+ if ($request->getHttpCode() == '200') {
+ // Got a 200 OK response, calculate the TTL to use for caching it
+ if (($expires = $request->getResponseHeader('Expires')) != null) {
+ // prefer to use the servers notion of the time since there could be a clock-skew, but otherwise use our own
+ $date = $request->getResponseHeader('Date') != null ? $request->getResponseHeader('Date') : gmdate('D, d M Y H:i:s', $_SERVER['REQUEST_TIME']) . ' GMT';
+ // convert both dates to unix epoch seconds, and calculate the TTL
+ $date = strtotime($date);
+ $expires = strtotime($expires);
+ $ttl = $expires - $date;
+ // Don't fall for the old expiration-date-in-the-past trick, we *really* want to cache stuff since a large SNS's traffic would devastate a gadget developer's server
+ if ($expires - $date > 1) {
+ $ttl = $expires - $date;
+ }
+ }
+ // See http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html : The Cache-Control: max-age=<seconds> overrides the expires header, sp if both are present this one will overwrite the $ttl
+ if (($cacheControl = $request->getResponseHeader('Cache-Control')) != null) {
+ $bits = explode('=', $cacheControl);
+ foreach ($bits as $key => $val) {
+ if ($val == 'max-age' && isset($bits[$key + 1])) {
+ $ttl = $bits[$key + 1];
+ break;
+ }
+ }
+ }
+ } else {
+ $ttl = 5 * 60; // cache errors for 5 minutes, takes the denial of service attack type behaviour out of having an error :)
+ }
+ $cache->set($request->toHash(), $request, $ttl);
+ }
+ }
}
Modified: incubator/shindig/trunk/php/src/common/sample/BasicRemoteContentFetcher.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/common/sample/BasicRemoteContentFetcher.php?rev=744970&r1=744969&r2=744970&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/common/sample/BasicRemoteContentFetcher.php (original)
+++ incubator/shindig/trunk/php/src/common/sample/BasicRemoteContentFetcher.php Tue Feb 17 11:53:06 2009
@@ -1,4 +1,5 @@
<?php
+
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
@@ -18,155 +19,151 @@
* under the License.
*/
-
/**
* Basic remote content fetcher, uses curl_multi to fetch multiple resources at the same time
*/
class BasicRemoteContentFetcher extends RemoteContentFetcher {
private $requests = array();
- const USER_AGENT = 'Shindig PHP';
+ private $disallowedHeaders = array('Keep-Alive', 'Host', 'Accept-Encoding', 'Set-Cookie', 'Content-Length', 'Content-Encoding', 'ETag', 'Last-Modified', 'Accept-Ranges', 'Vary', 'Expires', 'Date', 'Pragma', 'Cache-Control', 'Transfer-Encoding', 'If-Modified-Since');
+ const USER_AGENT = 'Apache Shindig';
- public function fetchRequest($request) {
- $request->handle = curl_init();
- curl_setopt($request->handle, CURLOPT_URL, $request->getUrl());
- curl_setopt($request->handle, CURLOPT_FOLLOWLOCATION, 1);
- curl_setopt($request->handle, CURLOPT_RETURNTRANSFER, 1);
- curl_setopt($request->handle, CURLOPT_AUTOREFERER, 1);
- curl_setopt($request->handle, CURLOPT_MAXREDIRS, 10);
- curl_setopt($request->handle, CURLOPT_CONNECTTIMEOUT, Config::get('curl_connection_timeout'));
- curl_setopt($request->handle, CURLOPT_TIMEOUT, 2);
- curl_setopt($request->handle, CURLOPT_HEADER, 1);
- curl_setopt($request->handle, CURLOPT_SSL_VERIFYPEER, 0);
- $proxy = Config::get('proxy');
- if (! empty($proxy)) {
- curl_setopt($request->handle, CURLOPT_PROXY, $proxy);
- }
- if ($request->hasHeaders()) {
- $headers = explode("\n", $request->getHeaders());
- $outHeaders = array();
- foreach ($headers as $header) {
- if (strpos($header, ':')) {
- $key = trim(substr($header, 0, strpos($header, ':')));
- $val = trim(substr($header, strpos($header, ':') + 1));
- if (strcmp($key, "User-Agent") != 0 && strcasecmp($key, "Transfer-Encoding") != 0 && strcasecmp($key, "Cache-Control") != 0 && strcasecmp($key, "Expires") != 0 && strcasecmp($key, "Content-Length") != 0) {
- $outHeaders[] = "$key: $val";
- }
- }
- }
- $outHeaders[] = "User-Agent: " . BasicRemoteContentFetcher::USER_AGENT;
- curl_setopt($request->handle, CURLOPT_HTTPHEADER, $outHeaders);
- }
- if ($request->isPost()) {
- curl_setopt($request->handle, CURLOPT_POST, 1);
- curl_setopt($request->handle, CURLOPT_POSTFIELDS, $request->getPostBody());
- }
+ /**
+ * Performs a single (RemoteContentRequest) request and fills in the response
+ * in the $request object
+ *
+ * @param RemoteContentRequest $request
+ * @return RemoteContentRequest $request
+ */
+ public function fetchRequest(RemoteContentRequest $request) {
+ $request->handle = $this->initCurlHandle($request->getUrl());
+ $this->setHeaders($request);
// Execute the request
$content = @curl_exec($request->handle);
- $header = '';
- $body = '';
- // on redirects and such we get multiple headers back from curl it seems, we really only want the last one
- while (substr($content, 0, strlen('HTTP')) == 'HTTP' && strpos($content, "\r\n\r\n") !== false) {
- $header = substr($content, 0, strpos($content, "\r\n\r\n"));
- $content = $body = substr($content, strlen($header) + 4);
- }
- $httpCode = curl_getinfo($request->handle, CURLINFO_HTTP_CODE);
- $contentType = curl_getinfo($request->handle, CURLINFO_CONTENT_TYPE);
- if (! $httpCode) {
- $httpCode = '404';
- }
- $request->setHttpCode($httpCode);
- $request->setContentType($contentType);
- $request->setResponseHeaders($header);
- $request->setResponseContent($body);
- $request->setResponseSize(strlen($content));
+ $this->parseResult($request, $content);
curl_close($request->handle);
unset($request->handle);
return $request;
}
+ /**
+ * Performs multiple (array of RemoteContentRequest) requests and fills in the responses
+ * in the $request objects
+ *
+ * @param Array of RemoteContentRequest's $requests
+ * @return $requests
+ */
public function multiFetchRequest(Array $requests) {
$mh = curl_multi_init();
foreach ($requests as $request) {
- $request->handle = curl_init();
- curl_setopt($request->handle, CURLOPT_URL, $request->getUrl());
- curl_setopt($request->handle, CURLOPT_FOLLOWLOCATION, 1);
- curl_setopt($request->handle, CURLOPT_RETURNTRANSFER, 1);
- curl_setopt($request->handle, CURLOPT_AUTOREFERER, 1);
- curl_setopt($request->handle, CURLOPT_MAXREDIRS, 10);
- curl_setopt($request->handle, CURLOPT_CONNECTTIMEOUT, Config::get('curl_connection_timeout'));
- curl_setopt($request->handle, CURLOPT_TIMEOUT, 2);
- curl_setopt($request->handle, CURLOPT_HEADER, 1);
- curl_setopt($request->handle, CURLOPT_SSL_VERIFYPEER, 0);
+ $request->handle = $this->initCurlHandle($request->getUrl());
// Set this so the multihandler will return data
curl_setopt($request->handle, CURLOPT_RETURNTRANSFER, 1);
-
- $proxy = Config::get('proxy');
- if (! empty($proxy)) {
- curl_setopt($request->handle, CURLOPT_PROXY, $proxy);
- }
- if ($request->hasHeaders()) {
- $headers = explode("\n", $request->getHeaders());
- $outHeaders = array();
- foreach ($headers as $header) {
- if (strpos($header, ':')) {
- $key = trim(substr($header, 0, strpos($header, ':')));
- $val = trim(substr($header, strpos($header, ':') + 1));
- if (strcmp($key, "User-Agent") != 0 && strcasecmp($key, "Transfer-Encoding") != 0 && strcasecmp($key, "Cache-Control") != 0 && strcasecmp($key, "Expires") != 0 && strcasecmp($key, "Content-Length") != 0) {
- $outHeaders[] = "$key: $val";
- }
- }
- }
- $outHeaders[] = "User-Agent: " . BasicRemoteContentFetcher::USER_AGENT;
- curl_setopt($request->handle, CURLOPT_HTTPHEADER, $outHeaders);
- }
- if ($request->isPost()) {
- curl_setopt($request->handle, CURLOPT_POST, 1);
- curl_setopt($request->handle, CURLOPT_POSTFIELDS, $request->getPostBody());
- }
+ $this->setHeaders($request);
curl_multi_add_handle($mh, $request->handle);
}
-
$running = null;
- //execute the handles
do {
curl_multi_exec($mh, $running);
} while ($running > 0);
-
- //Ideally this should be 0 after curl_multi_info_read() is call, meaning all
- //calls have bee processed
- $msg_queue = null;
- $responses = curl_multi_info_read($mh, $msg_queue);
-
foreach ($requests as $request) {
// Execute the request
$content = curl_multi_getcontent($request->handle);
- $header = '';
- $body = '';
- // on redirects and such we get multiple headers back from curl it seems, we really only want the last one
- while (substr($content, 0, strlen('HTTP')) == 'HTTP' && strpos($content, "\r\n\r\n") !== false) {
- $header = substr($content, 0, strpos($content, "\r\n\r\n"));
- $content = $body = substr($content, strlen($header) + 4);
- }
- $httpCode = curl_getinfo($request->handle, CURLINFO_HTTP_CODE);
- $contentType = curl_getinfo($request->handle, CURLINFO_CONTENT_TYPE);
- if (! $httpCode) {
- $httpCode = '404';
- }
- $request->setHttpCode($httpCode);
- $request->setContentType($contentType);
- $request->setResponseHeaders($header);
- $request->setResponseContent($body);
- $request->setResponseSize(strlen($content));
- }
-
- // close the handles
- foreach ($requests as $request) {
- curl_close($request->handle);
+ $this->parseResult($request, $content);
+ curl_multi_remove_handle($mh, $request->handle);
unset($request->handle);
}
curl_multi_close($mh);
unset($mh);
-
return $requests;
}
+
+ /**
+ * Parses the result content into the headers and body, and retrieves the http code and content type
+ *
+ * @param RemoteContentRequest $request
+ * @param string $content
+ */
+ private function parseResult(RemoteContentRequest $request, $content) {
+ $headers = '';
+ $body = '';
+ // on redirects and such we get multiple headers back from curl it seems, we really only want the last one
+ while (substr($content, 0, strlen('HTTP')) == 'HTTP' && strpos($content, "\r\n\r\n") !== false) {
+ $headers = substr($content, 0, strpos($content, "\r\n\r\n"));
+ $content = $body = substr($content, strlen($headers) + 4);
+ }
+ $headers = explode("\n", $headers);
+ $parsedHeaders = array();
+ foreach ($headers as $header) {
+ if (strpos($header, ':')) {
+ $key = trim(substr($header, 0, strpos($header, ':')));
+ $key = str_replace(' ', '-', ucwords(str_replace('-', ' ', $key)));
+ $val = trim(substr($header, strpos($header, ':') + 1));
+ $parsedHeaders[$key] = $val;
+ }
+ }
+ $httpCode = curl_getinfo($request->handle, CURLINFO_HTTP_CODE);
+ $contentType = curl_getinfo($request->handle, CURLINFO_CONTENT_TYPE);
+ if (! $httpCode) {
+ $httpCode = '404';
+ }
+ $request->setHttpCode($httpCode);
+ $request->setContentType($contentType);
+ $request->setResponseHeaders($parsedHeaders);
+ $request->setResponseContent($body);
+ $request->setResponseSize(strlen($content));
+ }
+
+ /**
+ * Sets the headers and post body for the request if they are specified
+ *
+ * @param RemoteContentRequest $request
+ */
+ private function setHeaders(RemoteContentRequest $request) {
+ if ($request->hasHeaders()) {
+ $headers = explode("\n", $request->getHeaders());
+ $outHeaders = array();
+ foreach ($headers as $header) {
+ if (strpos($header, ':')) {
+ $key = trim(substr($header, 0, strpos($header, ':')));
+ $key = str_replace(' ', '-', ucwords(str_replace('-', ' ', $key)));
+ $val = trim(substr($header, strpos($header, ':') + 1));
+ if (! in_array($key, $this->disallowedHeaders)) {
+ $outHeaders[] = "$key: $val";
+ }
+ }
+ }
+ $outHeaders[] = "User-Agent: " . BasicRemoteContentFetcher::USER_AGENT;
+ curl_setopt($request->handle, CURLOPT_HTTPHEADER, $outHeaders);
+ }
+ if ($request->isPost()) {
+ curl_setopt($request->handle, CURLOPT_POST, 1);
+ curl_setopt($request->handle, CURLOPT_POSTFIELDS, $request->getPostBody());
+ }
+ }
+
+ /**
+ * Initializes a curl handle for making a request
+ * This will set the timeout based on the 'curl_connection_timeout configuration', and
+ * set a proxy server to use if the 'proxy' config string is not empty
+ *
+ * @param string $url
+ * @return curl handle
+ */
+ private function initCurlHandle($url) {
+ $handle = curl_init();
+ curl_setopt($handle, CURLOPT_URL, $url);
+ curl_setopt($handle, CURLOPT_FOLLOWLOCATION, 1);
+ curl_setopt($handle, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($handle, CURLOPT_AUTOREFERER, 1);
+ curl_setopt($handle, CURLOPT_MAXREDIRS, 10);
+ curl_setopt($handle, CURLOPT_CONNECTTIMEOUT, Config::get('curl_connection_timeout'));
+ curl_setopt($handle, CURLOPT_TIMEOUT, 2);
+ curl_setopt($handle, CURLOPT_HEADER, 1);
+ curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, 0);
+ $proxy = Config::get('proxy');
+ if (! empty($proxy)) {
+ curl_setopt($handle, CURLOPT_PROXY, $proxy);
+ }
+ return $handle;
+ }
}
Modified: incubator/shindig/trunk/php/src/common/sample/CacheApc.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/common/sample/CacheApc.php?rev=744970&r1=744969&r2=744970&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/common/sample/CacheApc.php (original)
+++ incubator/shindig/trunk/php/src/common/sample/CacheApc.php Tue Feb 17 11:53:06 2009
@@ -50,40 +50,38 @@
}
private function waitForLock($key) {
- // 20 x 250 = 5 seconds
- $tries = 20;
+ // 10 x 100ms = 1 second
+ $tries = 10;
$cnt = 0;
do {
- // 250 ms is a long time to sleep, but it does stop the server from burning all resources on polling locks..
- usleep(250);
+ usleep(100);
$cnt ++;
} while ($cnt <= $tries && $this->isLocked());
if ($this->isLocked()) {
- // 5 seconds passed, assume the owning process died off and remove it
$this->removeLock($key);
}
}
- public function get($key, $expiration = false) {
- if (! $expiration) {
- // default to global cache time
- $expiration = Config::Get('cache_time');
- }
+ public function get($key) {
if (($ret = @apc_fetch($key)) === false) {
return false;
}
- if (time() - $ret['time'] > $expiration) {
- $this->delete($key);
- return false;
- }
- return unserialize($ret['data']);
+ return $ret;
}
- public function set($key, $value) {
- // we store it with the cache_time default expiration so objects will atleast get cleaned eventually.
- if (@apc_store($key, array('time' => time(), 'data' => serialize($value)), Config::Get('cache_time')) == false) {
+ public function set($key, $value, $ttl = false) {
+ if (! $ttl) {
+ $ttl = Config::Get('cache_time');
+ }
+ if ($this->isLocked($key)) {
+ $this->waitForLock($key);
+ }
+ $this->createLock($key);
+ if (@apc_store($key, $value, $ttl) == false) {
+ $this->removeLock($key);
throw new CacheException("Couldn't store data in cache");
}
+ $this->removeLock($key);
}
public function delete($key) {
Modified: incubator/shindig/trunk/php/src/common/sample/CacheFile.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/common/sample/CacheFile.php?rev=744970&r1=744969&r2=744970&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/common/sample/CacheFile.php (original)
+++ incubator/shindig/trunk/php/src/common/sample/CacheFile.php Tue Feb 17 11:53:06 2009
@@ -1,4 +1,5 @@
<?php
+
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
@@ -18,13 +19,12 @@
* under the License.
*/
-
/*
* This class impliments a basic on disk caching. That will work fine on a single host
* but on a multi server setup this could lead to some problems due to inconsistencies
* between the various cached versions on the different servers. Other methods like
* memcached should be used instead really.
- *
+ *
* When using this file based backend, its adviced to make a cron job that scans thru the
* cache dir, and removes all files that are older then 24 hours (or whatever your
* config's CACHE_TIME is set too).
@@ -55,14 +55,13 @@
}
private function waitForLock($cacheFile) {
- // 20 x 250 = 5 seconds
- $tries = 20;
+ // 10 x 100 = 1 second
+ $tries = 10;
$cnt = 0;
do {
// make sure PHP picks up on file changes. This is an expensive action but really can't be avoided
clearstatcache();
- // 250 ms is a long time to sleep, but it does stop the server from burning all resources on polling locks..
- usleep(250);
+ usleep(100);
$cnt ++;
} while ($cnt <= $tries && $this->isLocked($cacheFile));
if ($this->isLocked($cacheFile)) {
@@ -82,11 +81,7 @@
return $this->getCacheDir($hash) . '/' . $hash;
}
- public function get($key, $expiration = false) {
- if (! $expiration) {
- // if no expiration time was given, fall back on the global config
- $expiration = Config::get('cache_time');
- }
+ public function get($key) {
$cacheFile = $this->getCacheFile($key);
// See if this cache file is locked, if so we wait upto 5 seconds for the lock owning process to
// complete it's work. If the lock is not released within that time frame, it's cleaned up.
@@ -95,18 +90,20 @@
$this->waitForLock($cacheFile);
}
if (File::exists($cacheFile) && File::readable($cacheFile)) {
- $now = time();
- if (($mtime = @filemtime($cacheFile)) !== false && ($now - $mtime) < $expiration) {
- if (($data = @file_get_contents($cacheFile)) !== false) {
- $data = unserialize($data);
- return $data;
+ if (($data = @file_get_contents($cacheFile)) !== false) {
+ $data = unserialize($data);
+ if (($_SERVER['REQUEST_TIME'] - $data['time']) < $data['ttl']) {
+ return $data['data'];
}
}
}
return false;
}
- public function set($key, $value) {
+ public function set($key, $value, $ttl = false) {
+ if (! $ttl) {
+ $ttl = Config::Get('cache_time');
+ }
$cacheDir = $this->getCacheDir($key);
$cacheFile = $this->getCacheFile($key);
if ($this->isLocked($cacheFile)) {
@@ -118,9 +115,7 @@
throw new CacheException("Could not create cache directory");
}
}
- // we serialize the whole request object, since we don't only want the
- // responseContent but also the postBody used, headers, size, etc
- $data = serialize($value);
+ $data = serialize(array('data' => $value, 'time' => $_SERVER['REQUEST_TIME'], 'ttl' => $ttl));
$this->createLock($cacheFile);
if (! @file_put_contents($cacheFile, $data)) {
$this->removeLock($cacheFile);
Modified: incubator/shindig/trunk/php/src/common/sample/CacheMemcache.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/common/sample/CacheMemcache.php?rev=744970&r1=744969&r2=744970&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/common/sample/CacheMemcache.php (original)
+++ incubator/shindig/trunk/php/src/common/sample/CacheMemcache.php Tue Feb 17 11:53:06 2009
@@ -52,7 +52,7 @@
$this->check();
// the interesting thing is that this could fail if the lock was created in the meantime..
// but we'll ignore that out of convenience
- @memcache_add($this->connection, $key . '.lock', '', 0, 5);
+ @memcache_add($this->connection, $key . '.lock', '', 0, 2);
}
private function removeLock($key) {
@@ -63,22 +63,18 @@
private function waitForLock($key) {
$this->check();
- // 20 x 250 = 5 seconds
- $tries = 20;
+ $tries = 10;
$cnt = 0;
do {
- // 250 ms is a long time to sleep, but it does stop the server from burning all resources on polling locks..
- usleep(250);
+ usleep(100);
$cnt ++;
} while ($cnt <= $tries && $this->isLocked());
if ($this->isLocked()) {
- // 5 seconds passed, assume the owning process died off and remove it
$this->removeLock($key);
}
}
- // I prefer lazy initalization since the cache isn't used every request
- // so this potentially saves a lot of overhead
+ // Prefer lazy initalization since the cache isn't used every request
private function connect() {
if (! $this->connection = @memcache_pconnect($this->host, $this->port)) {
throw new CacheException("Couldn't connect to memcache server");
@@ -107,13 +103,20 @@
return $ret['data'];
}
- public function set($key, $value) {
+ public function set($key, $value, $ttl = false) {
$this->check();
- // we store it with the cache_time default expiration so objects will atleast get cleaned eventually.
- if (@memcache_set($this->connection, $key, array('time' => time(),
- 'data' => $value), false, Config::Get('cache_time')) == false) {
+ if (! $ttl) {
+ $ttl = Config::Get('cache_time');
+ }
+ if ($this->isLocked($key)) {
+ $this->waitForLock($key);
+ }
+ $this->createLock($key);
+ if (@memcache_set($this->connection, $key, $value, false, $ttl) == false) {
+ $this->removeLock($key);
throw new CacheException("Couldn't store data in cache");
}
+ $this->removeLock($key);
}
public function delete($key) {
Modified: incubator/shindig/trunk/php/src/gadgets/SigningFetcher.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/SigningFetcher.php?rev=744970&r1=744969&r2=744970&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/SigningFetcher.php (original)
+++ incubator/shindig/trunk/php/src/gadgets/SigningFetcher.php Tue Feb 17 11:53:06 2009
@@ -28,25 +28,25 @@
* but instances may be created by multiple threads.
*/
class SigningFetcher extends RemoteContentFetcher {
-
+
protected static $OPENSOCIAL_OWNERID = "opensocial_owner_id";
protected static $OPENSOCIAL_VIEWERID = "opensocial_viewer_id";
protected static $OPENSOCIAL_APPID = "opensocial_app_id";
protected static $XOAUTH_PUBLIC_KEY = "xoauth_signature_publickey";
protected static $ALLOWED_PARAM_NAME = '^[-_[:alnum:]]+$';
-
+
/**
* Authentication token for the user and gadget making the request.
*/
protected $authToken;
-
+
/**
* Private key we pass to the OAuth RSA_SHA1 algorithm.This can be a
* PrivateKey object, or a PEM formatted private key, or a DER encoded byte
* array for the private key.(No, really, they accept any of them.)
*/
protected $privateKeyObject;
-
+
/**
* The name of the key, included in the fetch to help with key rotation.
*/
@@ -92,7 +92,7 @@
$this->privateKeyObject = $privateKeyObject;
}
- public function fetchRequest($request) {
+ public function fetchRequest(RemoteContentRequest $request) {
return $this->getNextFetcher()->fetchRequest($request);
}