Permalink
Browse files

ETags support

  • Loading branch information...
1 parent 71976b0 commit d507021ffb34a17d2d35ca559be809fbb972b118 @bartekn committed Jun 28, 2012
Showing with 113 additions and 0 deletions.
  1. +93 −0 src/base_facebook.php
  2. +20 −0 tests/tests.php
View
@@ -201,6 +201,27 @@ public function __toString() {
protected $fileUploadSupport = false;
/**
+ * ETag to be sent with "If-None-Match" header
+ *
+ * @var string
+ */
+ protected $etagSend = null;
+
+ /**
+ * ETag received from last API call
+ *
+ * @var string
+ */
+ protected $etagReceived = '';
+
+ /**
+ * True if ETag has not changed (hit), false if ETag has changed (miss)
+ *
+ * @var boolean
+ */
+ protected $etagHit;
+
+ /**
* Initialize a Facebook Application.
*
* The configuration:
@@ -861,6 +882,20 @@ protected function makeRequest($url, $params, $ch=null) {
}
$opts[CURLOPT_URL] = $url;
+ // Enable header processing
+ $opts[CURLOPT_HEADER] = 1;
+
+ // ETags
+ if ($this->etagSend != null)
+ {
+ if (isset($opts[CURLOPT_HTTPHEADER])) {
+ $opts[CURLOPT_HTTPHEADER][] = 'If-None-Match: '.$this->etagSend;
+ } else {
+ $opts[CURLOPT_HTTPHEADER] = array('If-None-Match: '.$this->etagSend);
+ }
+ $this->etagSend = null;
+ }
+
// disable the 'Expect: 100-continue' behaviour. This causes CURL to wait
// for 2 seconds if the server does not support this header.
if (isset($opts[CURLOPT_HTTPHEADER])) {
@@ -912,11 +947,69 @@ protected function makeRequest($url, $params, $ch=null) {
curl_close($ch);
throw $e;
}
+ else
+ {
+ $info = curl_getinfo($ch);
+ if ($info['http_code'] == 304)
+ {
+ $this->etagHit = true;
+ }
+ else
+ {
+ $this->etagHit = false;
+ }
+ $headers = mb_substr($result, 0, $info['header_size']);
+ $result = mb_substr($result, -$info['download_content_length']);
+
+ if (($etag_pos = strpos($headers, 'ETag: ')) !== FALSE)
+ {
+ $etag_pos += 6;
+ $this->etagReceived = substr($headers, $etag_pos,
+ strpos($headers, chr(10), $etag_pos)-$etag_pos-1);
+ }
+ else
+ {
+ $this->etagReceived = '';
+ }
+ }
curl_close($ch);
return $result;
}
/**
+ * Sets ETag to be sent with the next API call.
+ * After the next API call $this->etagSend value is set to null.
+ *
+ * @param String Etag
+ */
+ public function setETag($etag)
+ {
+ $this->etagSend = $etag;
+ }
+
+ /**
+ * Returns ETag received from the last API call.
+ * Returns empty string if the data has not changed - hit.
+ *
+ * @return String Etag
+ */
+ public function getReceivedETag()
+ {
+ return $this->etagReceived;
+ }
+
+ /**
+ * Determines whether data has not changed (hit).
+ * When data has changed method returns false.
+ *
+ * @return Boolean true if data has not changed - hit
+ */
+ public function isETagHit()
+ {
+ return $this->etagHit;
+ }
+
+ /**
* Parses a signed_request and validates the signature.
*
* @param string $signed_request A signed token
View
@@ -821,6 +821,24 @@ public function testGetUserWithoutCodeOrSignedRequestOrSession() {
'Session superglobal incorrectly populated by getUser.');
}
+ public function testETags() {
+ $facebook = new TransientFacebook(array(
+ 'appId' => self::APP_ID,
+ 'secret' => self::SECRET,
+ ));
+
+ $query = '/zuck';
+
+ $result = $facebook->api($query);
+ $etag = $facebook->getReceivedETag();
+
+ $facebook->setETag($etag);
+ $facebook->api($query);
+ $etag_hit = $facebook->isETagHit();
+
+ $this->assertTrue($etag_hit);
+ }
+
protected function generateMD5HashOfRandomValue() {
return md5(uniqid(mt_rand(), true));
}
@@ -863,6 +881,8 @@ protected function assertIsSubset($correct, $actual, $msg='') {
}
}
+require '../src/facebook.php';
+
class TransientFacebook extends BaseFacebook {
protected function setPersistentData($key, $value) {}
protected function getPersistentData($key, $default = false) {

0 comments on commit d507021

Please sign in to comment.