You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@shindig.apache.org by ch...@apache.org on 2009/09/05 16:18:28 UTC

svn commit: r811651 - in /incubator/shindig/trunk/php/src/gadgets: GadgetContext.php MakeRequest.php MakeRequestHandler.php MakeRequestOptions.php ProxyBase.php servlet/MakeRequestServlet.php

Author: chabotc
Date: Sat Sep  5 14:18:27 2009
New Revision: 811651

URL: http://svn.apache.org/viewvc?rev=811651&view=rev
Log:
Issue 105099 by Arne Roomann-Kurrik: Refactored to use MakeRequestOptions class instead of a parameter array

Added:
    incubator/shindig/trunk/php/src/gadgets/MakeRequest.php
    incubator/shindig/trunk/php/src/gadgets/MakeRequestOptions.php
Modified:
    incubator/shindig/trunk/php/src/gadgets/GadgetContext.php
    incubator/shindig/trunk/php/src/gadgets/MakeRequestHandler.php
    incubator/shindig/trunk/php/src/gadgets/ProxyBase.php
    incubator/shindig/trunk/php/src/gadgets/servlet/MakeRequestServlet.php

Modified: incubator/shindig/trunk/php/src/gadgets/GadgetContext.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/GadgetContext.php?rev=811651&r1=811650&r2=811651&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/GadgetContext.php (original)
+++ incubator/shindig/trunk/php/src/gadgets/GadgetContext.php Sat Sep  5 14:18:27 2009
@@ -263,7 +263,7 @@
    * signer to validate the token
    *
    * @param SecurityTokenDecoder $signer the signer to use (configured in config.php)
-   * @return string the token to use in the signed url
+   * @return SecurityToken An object representation of the token data.
    */
   public function extractAndValidateToken($signer) {
     if ($signer == null) {
@@ -273,6 +273,17 @@
     if (! isset($token) || $token == '') {
       $token = isset($_POST['st']) ? $_POST['st'] : '';
     }
+    return $this->validateToken($token, $signer);
+  }
+
+  /**
+   * Validates a passed-in token.
+   * 
+   * @param string $token A urlencoded base64 encoded security token.
+   * @param SecurityTokenDecoder $signer The signer to use (configured in config.php)
+   * @return SecurityToken An object representation of the token data.
+   */
+  public function validateToken($token, $signer) {
     if (count(explode(':', $token)) != 7) {
       $token = urldecode(base64_decode($token));
     }

Added: incubator/shindig/trunk/php/src/gadgets/MakeRequest.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/MakeRequest.php?rev=811651&view=auto
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/MakeRequest.php (added)
+++ incubator/shindig/trunk/php/src/gadgets/MakeRequest.php Sat Sep  5 14:18:27 2009
@@ -0,0 +1,340 @@
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+require_once 'src/gadgets/MakeRequestOptions.php';
+
+/**
+ * Common class for working with remote content requests.
+ * Example - sending a request from a gadget context:
+ * <code>
+ *   $context = new GadgetContext('GADGET');
+ *   $params = new MakeRequestOptions('http://www.example.com');
+ *   $params->setAuthz('SIGNED')
+ *          ->setNoCache(true)
+ *          ->setSignViewer(false)
+ *          ->setSecurityTokenString($_GET('st'));
+ *   $result = $this->makeRequest->fetch($context, $params);
+ *   $responseCode = $result->getHttpCode();
+ *   $responseText = $result->getResponseContent();
+ * </code>
+ * More examples can be found in the
+ * {@link /php/src/test/gadgets/MakeRequestTest.php} MakeRequest unit tests.
+ */
+
+class MakeRequest {
+
+  private $remoteFetcher;
+
+  /**
+   * Constructor
+   *
+   * @param RemoteContentFetcher remoteFetcher A remote content fetcher intended
+   *     to override the default fetcher which will be loaded from the config
+   *     file.  This allows for injecting a mock into this class for testing.
+   */
+  public function __construct($remoteFetcher = null){
+    if (isset($remoteFetcher)) {
+      $this->remoteFetcher = $remoteFetcher;
+    } else {
+      $remoteFetcherClass = Config::get('remote_content_fetcher');
+      $this->remoteFetcher = new $remoteFetcherClass();
+    }
+  }
+
+  /**
+   * Returns the remote fetcher this instance uses for remote requests.
+   *
+   * @return RemoteContentFetcher
+   */
+  public function getRemoteFetcher() {
+    return $this->remoteFetcher;
+  }
+
+  /**
+   * Makes a request for remote data.
+   *
+   * @param GadgetContext $context Gadget context used to make the request.
+   * @param MakeRequestOptions $params Parameter array used to configure the remote request.
+   * @return RemoteContentRequest A request/response which has been sent to the target server.
+   */
+  public function fetch(GadgetContext $context, MakeRequestOptions $params) {
+
+    $signingFetcherFactory = $gadgetSigner = null;
+    if ($params->getAuthz() == "SIGNED") {
+      $gadgetSigner = Config::get('security_token_signer');
+      $gadgetSigner = new $gadgetSigner();
+      $signingFetcherFactory = new SigningFetcherFactory(Config::get("private_key_file"));
+    }
+
+    $basicRemoteContent = new BasicRemoteContent($this->remoteFetcher, $signingFetcherFactory, $gadgetSigner);
+
+    $request = $this->buildRequest($context, $params, $gadgetSigner);
+    $request->getOptions()->ignoreCache = $params->getNoCache();
+    $request->getOptions()->viewerSigned = $params->getSignViewer();
+    $request->getOptions()->ownerSigned = $params->getSignOwner(); 
+    $result = $basicRemoteContent->fetch($request);
+
+    $status = (int)$result->getHttpCode();
+    if ($status == 200) {
+      switch ($params->getResponseFormat()) {
+        case 'FEED':
+          $content = $this->parseFeed($result, $params->getHref(), $params->getNumEntries(), $params->getGetSummaries());
+          $result->setResponseContent($content);
+          break;
+      }
+    }
+
+    return $result;
+  }
+
+  /**
+   * Builds a request to retrieve the actual content.
+   *
+   * @param GadgetContext $context The rendering context.
+   * @param MakeRequestOptions $params Options for crafting the request.
+   * @param SecurityTokenDecoder $signer A signer needed for signed requests.
+   * @return RemoteContentRequest An initialized request object.
+   */
+  public function buildRequest(GadgetContext $context, MakeRequestOptions $params, SecurityTokenDecoder $signer = null) {
+    // Check the protocol requested - curl doesn't really support file://
+    // requests but the 'error' should be handled properly
+    $protocolSplit = explode('://', $params->getHref(), 2);
+    if (count($protocolSplit) < 2) {
+      throw new Exception("Invalid protocol specified");
+    } 
+
+    $protocol = strtoupper($protocolSplit[0]);
+    if ($protocol != "HTTP" && $protocol != "HTTPS") {
+      throw new Exception("Invalid protocol specified in url: " . htmlentities($protocol));
+    }
+
+    $method = $params->getHttpMethod();
+    if ($method == 'POST' || $method == 'PUT') {
+       // even if postData is an empty string, it will still post
+       // (since RemoteContentRquest checks if its false)
+       // so the request to POST is still honored
+       $request = new RemoteContentRequest($params->getHref(), null, $params->getRequestBody());
+    } else {
+       $request = new RemoteContentRequest($params->getHref());
+    }
+
+    if ($signer) {
+      switch ($params->getAuthz()) {
+        case 'SIGNED':
+          $request->setAuthType(RemoteContentRequest::$AUTH_SIGNED);
+          break;
+        case 'OAUTH':
+          $request->setAuthType(RemoteContentRequest::$AUTH_OAUTH);
+          $request->setOAuthRequestParams($params->getOAuthRequestParameters());
+          break;
+      }
+      
+      $st = $params->getSecurityTokenString();
+      if ($st === false) {
+        throw new Exception("A security token is required for signed requests");
+      }
+      $token = $context->validateToken($st, $signer);
+      $request->setToken($token);
+    }
+
+    $headers = $params->getFormattedRequestHeaders();
+    if ($headers !== false) {
+      // The request expects headers to be stored as a normal header text blob.
+      // ex: Content-Type: application/atom+xml
+      //     Accept-Language: en-us
+      $request->setHeaders($headers);
+    }
+    
+    return $request;
+  }
+
+
+  /**
+   * Handles (RSS & Atom) Type.FEED parsing using Zend's feed parser
+   *
+   * @return response string, either a json encoded feed structure or an error message
+   */
+  private function parseFeed($result, $url, $numEntries = 3, $getSummaries = false) {
+    require 'external/Zend/Feed.php';
+    $channel = array();
+    if ((int)$result->getHttpCode() == 200) {
+      $content = $result->getResponseContent();
+      try {
+        $feed = Zend_Feed::importString($content);
+        if ($feed instanceof Zend_Feed_Rss) {
+          // Try get author
+          if ($feed->author()) {
+            $author = $feed->author();
+          } else {
+            if ($feed->creator()) {
+              $author = $feed->creator();
+            } else {
+              $author = null;
+            }
+          }
+          // Loop over each channel item and store relevant data
+          $counter = 0;
+          $channel['Entry'] = array();
+          foreach ($feed as $item) {
+            if ($counter >= $numEntries) {
+              break;
+            }
+            $_entry = array();
+            $_entry['Title'] = $item->title();
+            $_entry['Link'] = $item->link();
+            if ($getSummaries && $item->description()) {
+              $_entry['Summary'] = $item->description();
+            }
+            $date = 0;
+            if ($item->date()) {
+              $date = strtotime($item->date());
+            } else {
+              if ($item->pubDate()) {
+                $date = strtotime($item->pubDate());
+              }
+            }
+            $_entry['Date'] = $date;
+            $channel['Entry'][] = $_entry;
+            // Remember author if first found
+            if (empty($author) && $item->author()) {
+              $author = $item->author();
+            } else if ($item->creator()) {
+              $author = $item->creator();
+            }
+            $counter ++;
+          }
+          $channel['Title'] = $feed->title();
+          $channel['URL'] = $url;
+          $channel['Description'] = $feed->description();
+          if ($feed->link()) {
+            if (is_array($feed->link())) {
+              foreach ($feed->link() as $_link) {
+                if ($_link->nodeValue) $channel['Link'] = $_link->nodeValue;
+              }
+            } else {
+              $channel['Link'] = $feed->link();
+            }
+          }
+          if ($author != null) {
+            $channel['Author'] = $author;
+          }
+        } elseif ($feed instanceof Zend_Feed_Atom) {
+          // Try get author
+          if ($feed->author()) {
+            if ($feed->author->name()) {
+              $author = $feed->author->name();
+            } else if ($feed->author->email()) {
+              $author = $feed->author->email();
+            } else {
+              $author = $feed->author();
+            }
+          } else {
+            $author = null;
+          }
+          // Loop over each entries and store relevant data
+          $counter = 0;
+          $channel['Entry'] = array();
+          foreach ($feed as $entry) {
+            if ($counter >= $numEntries) {
+              break;
+            }
+            $_entry = array();
+            $_entry['Title'] = $entry->title();
+            // get Link if rel="alternate"
+            if ($entry->link('alternate')) {
+              $_entry['Link'] = $entry->link('alternate');
+            } else {
+              // if there's no alternate, pick the one without "rel" attribtue
+              $_links = $entry->link;
+              if (is_array($_links)) {
+                foreach ($_links as $_link) {
+                  if (empty($_link['rel'])) {
+                    $_entry['Link'] = $_link['href'];
+                    break;
+                  }
+                }
+              } else {
+                $_entry['Link'] = $_links['href'];
+              }
+            }
+            if ($getSummaries && $entry->summary()) {
+              $_entry['Summary'] = $entry->summary();
+            }
+            $date = 0;
+            if ($entry->updated()) {
+              $date = strtotime($entry->updated());
+            } else {
+              if ($entry->published()) {
+                $date = strtotime($entry->published());
+              }
+            }
+            $_entry['Date'] = $date;
+            $channel['Entry'][] = $_entry;
+            // Remember author if first found
+            if (empty($author) && $entry->author()) {
+              if ($entry->author->name()) {
+                $author = $entry->author->name();
+              } else if ($entry->author->email()) {
+                $author = $entry->author->email();
+              } else {
+                $author = $entry->author();
+              }
+            } elseif (empty($author)) {
+              $author = null;
+            }
+            $counter ++;
+          }
+          $channel['Title'] = $feed->title();
+          $channel['URL'] = $url;
+          $channel['Description'] = $feed->subtitle();
+          // get Link if rel="alternate"
+          if ($feed->link('alternate')) {
+            $channel['Link'] = $feed->link('alternate');
+          } else {
+            // if there's no alternate, pick the one without "rel" attribtue
+            $_links = $feed->link;
+            if (is_array($_links)) {
+              foreach ($_links as $_link) {
+                if (empty($_link['rel'])) {
+                  $channel['Link'] = $_link['href'];
+                  break;
+                }
+              }
+            } else {
+              $channel['Link'] = $_links['href'];
+            }
+          }
+          if (! empty($author)) {
+            $channel['Author'] = $author;
+          }
+        } else {
+          throw new Exception('Invalid feed type');
+        }
+        $resp = json_encode($channel);
+      } catch (Zend_Feed_Exception $e) {
+        $resp = 'Error parsing feed: ' . $e->getMessage();
+      }
+    } else {
+      // feed import failed
+      $resp = "Error fetching feed, response code: " . $result->getHttpCode();
+    }
+    return $resp;
+  }
+}

Modified: incubator/shindig/trunk/php/src/gadgets/MakeRequestHandler.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/MakeRequestHandler.php?rev=811651&r1=811650&r2=811651&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/MakeRequestHandler.php (original)
+++ incubator/shindig/trunk/php/src/gadgets/MakeRequestHandler.php Sat Sep  5 14:18:27 2009
@@ -18,6 +18,8 @@
  * under the License.
  */
 
+require_once 'src/gadgets/MakeRequest.php';
+
 // according to features/core/io.js, this is high on the list of things to scrap
 define('UNPARSEABLE_CRUFT', "throw 1; < don't be evil' >");
 
@@ -25,254 +27,40 @@
  * Handles the gadget.io.makeRequest requests
  */
 class MakeRequestHandler extends ProxyBase {
+
   /**
-   * @var SingingFetcherFactory
+   * Constructor.
+   *
+   * @param GadgetContext $context Current rendering context
    */
-  private $signingFetcherFactory;
-  
-  public function __construct($context, $signingFetcherFactory) {
+  public function __construct(GadgetContext $context) {
     $this->context = $context;
-    $this->signingFetcherFactory = $signingFetcherFactory;
+    $this->makeRequest = new MakeRequest();
   }
-
+  
   /**
-   * Fetches content and returns it in JSON format
-   *
-   * @param string $url the url to fetch
-   * @param GadgetSigner $signer the request signer to use
-   * @param string $method the http method to use (get or post) in making the request
+   * Fetches content and echoes it in JSON format
+   * 
+   * @param MakeRequestOptions $params  The request configuration.
    */
-  public function fetchJson($url, $signer, $method) {
-    $url = $this->validateUrl($url);
-    // Fetch the content and convert it into JSON.
-    // TODO: Fetcher needs to handle variety of HTTP methods.
-    $result = $this->fetchContentDivert($url, $method, $signer);
-    if (! isset($result)) {
-      //OAuthFetcher only
-      $metadata = $this->oauthFetcher->getResponseMetadata();
-      $json = array($url => $metadata);
-      $json = json_encode($json);
-      $output = UNPARSEABLE_CRUFT . $json;
-      $this->setCachingHeaders();
-      header("Content-Type: application/json; charset=utf-8", true);
-      echo $output;
-      die();
-    }
-    $status = (int)$result->getHttpCode();
-    header("Content-Type: application/json; charset=utf-8", true);
-    $output = '';
-    if (isset($_REQUEST['contentType']) && $_REQUEST['contentType'] == 'FEED' && $status == 200) {
-      $body = $this->parseFeed($result, $url);
-    } else {
-      $body = $result->getResponseContent();
-    }
-    $responseArray = array('body' => $body, 'rc' => $status);
-    foreach ($result->getMetadatas() as $key => $value) {
-      $responseArray[$key] = $value;
-    }
-    $json = array($url => $responseArray);
+  public function fetchJson(MakeRequestOptions $params) {
+    $result = $this->makeRequest->fetch($this->context, $params);
+
+    $responseArray = array(
+      'body' => $result->getResponseContent(),
+      'rc' => (int)$result->getHttpCode(),
+      'headers' => $result->getResponseHeaders()
+    );
+    
+    array_merge($responseArray, $result->getMetadatas());
+
+    $json = array($params->getHref() => $responseArray);
     $json = json_encode($json);
     $output = UNPARSEABLE_CRUFT . $json;
-    if ($status == 200) {
+    if ($responseArray['rc'] == 200) {
       // only set caching headers if the result was 'OK'
       $this->setCachingHeaders();
     }
     echo $output;
   }
-
-  /**
-   * Fetches content using either OAUTH, SIGNED or NONE type signing
-   *
-   * @param string $url
-   * @param string $method
-   * @param SecurityTokenDecoder $signer
-   * @return RemoteContentRequest
-   */
-  private function fetchContentDivert($url, $method, $signer) {
-    $basicFetcher = new BasicRemoteContentFetcher();
-    $basicRemoteContent = new BasicRemoteContent($basicFetcher, $this->signingFetcherFactory, $signer);
-    $request = $this->buildRequest($url, $method, $signer);
-    $request->getOptions()->ignoreCache = $this->context->getIgnoreCache();
-    if (! empty($_REQUEST['signViewer']) && $_REQUEST['signViewer'] == 'false') {
-      $request->getOptions()->viewerSigned = false;
-    }
-    if (! empty($_REQUEST['signOwner']) && $_REQUEST['signOwner'] == 'false') {
-      $request->getOptions()->ownerSigned = false;
-    }
-    return $basicRemoteContent->fetch($request);
-  }
-
-  /**
-   * Handles (RSS & Atom) Type.FEED parsing using Zend's feed parser
-   *
-   * @return response string, either a json encoded feed structure or an error message
-   */
-  private function parseFeed($result, $url) {
-    require 'external/Zend/Feed.php';
-    $numEntries = $_REQUEST['numEntries'];
-    $getSummaries = ! empty($_REQUEST['getSummaries']) && $_REQUEST['getSummaries'] != 'false' ? true : false;
-    $channel = array();
-    if ((int)$result->getHttpCode() == 200) {
-      $content = $result->getResponseContent();
-      try {
-        $feed = Zend_Feed::importString($content);
-        if ($feed instanceof Zend_Feed_Rss) {
-          // Try get author
-          if ($feed->author()) {
-            $author = $feed->author();
-          } else {
-            if ($feed->creator()) {
-              $author = $feed->creator();
-            } else {
-              $author = null;
-            }
-          }
-          // Loop over each channel item and store relevant data
-          $counter = 0;
-          $channel['Entry'] = array();
-          foreach ($feed as $item) {
-            if ($counter >= $numEntries) {
-              break;
-            }
-            $_entry = array();
-            $_entry['Title'] = $item->title();
-            $_entry['Link'] = $item->link();
-            if ($getSummaries && $item->description()) {
-              $_entry['Summary'] = $item->description();
-            }
-            $date = 0;
-            if ($item->date()) {
-              $date = strtotime($item->date());
-            } else {
-              if ($item->pubDate()) {
-                $date = strtotime($item->pubDate());
-              }
-            }
-            $_entry['Date'] = $date;
-            $channel['Entry'][] = $_entry;
-            // Remember author if first found
-            if (empty($author) && $item->author()) {
-              $author = $item->author();
-            } else if ($item->creator()) {
-              $author = $item->creator();
-            }
-            $counter ++;
-          }
-          $channel['Title'] = $feed->title();
-          $channel['URL'] = $url;
-          $channel['Description'] = $feed->description();
-          if ($feed->link()) {
-            if (is_array($feed->link())) {
-              foreach ($feed->link() as $_link) {
-                if ($_link->nodeValue) $channel['Link'] = $_link->nodeValue;
-              }
-            } else {
-              $channel['Link'] = $feed->link();
-            }
-          }
-          if ($author != null) {
-            $channel['Author'] = $author;
-          }
-        } elseif ($feed instanceof Zend_Feed_Atom) {
-          // Try get author
-          if ($feed->author()) {
-            if ($feed->author->name()) {
-              $author = $feed->author->name();
-            } else if ($feed->author->email()) {
-              $author = $feed->author->email();
-            } else {
-              $author = $feed->author();
-            }
-          } else {
-            $author = null;
-          }
-          // Loop over each entries and store relevant data
-          $counter = 0;
-          $channel['Entry'] = array();
-          foreach ($feed as $entry) {
-            if ($counter >= $numEntries) {
-              break;
-            }
-            $_entry = array();
-            $_entry['Title'] = $entry->title();
-            // get Link if rel="alternate"
-            if ($entry->link('alternate')) {
-              $_entry['Link'] = $entry->link('alternate');
-            } else {
-              // if there's no alternate, pick the one without "rel" attribtue
-              $_links = $entry->link;
-              if (is_array($_links)) {
-                foreach ($_links as $_link) {
-                  if (empty($_link['rel'])) {
-                    $_entry['Link'] = $_link['href'];
-                    break;
-                  }
-                }
-              } else {
-                $_entry['Link'] = $_links['href'];
-              }
-            }
-            if ($getSummaries && $entry->summary()) {
-              $_entry['Summary'] = $entry->summary();
-            }
-            $date = 0;
-            if ($entry->updated()) {
-              $date = strtotime($entry->updated());
-            } else {
-              if ($entry->published()) {
-                $date = strtotime($entry->published());
-              }
-            }
-            $_entry['Date'] = $date;
-            $channel['Entry'][] = $_entry;
-            // Remember author if first found
-            if (empty($author) && $entry->author()) {
-              if ($entry->author->name()) {
-                $author = $entry->author->name();
-              } else if ($entry->author->email()) {
-                $author = $entry->author->email();
-              } else {
-                $author = $entry->author();
-              }
-            } elseif (empty($author)) {
-              $author = null;
-            }
-            $counter ++;
-          }
-          $channel['Title'] = $feed->title();
-          $channel['URL'] = $url;
-          $channel['Description'] = $feed->subtitle();
-          // get Link if rel="alternate"
-          if ($feed->link('alternate')) {
-            $channel['Link'] = $feed->link('alternate');
-          } else {
-            // if there's no alternate, pick the one without "rel" attribtue
-            $_links = $feed->link;
-            if (is_array($_links)) {
-              foreach ($_links as $_link) {
-                if (empty($_link['rel'])) {
-                  $channel['Link'] = $_link['href'];
-                  break;
-                }
-              }
-            } else {
-              $channel['Link'] = $_links['href'];
-            }
-          }
-          if (! empty($author)) {
-            $channel['Author'] = $author;
-          }
-        } else {
-          throw new Exception('Invalid feed type');
-        }
-        $resp = json_encode($channel);
-      } catch (Zend_Feed_Exception $e) {
-        $resp = 'Error parsing feed: ' . $e->getMessage();
-      }
-    } else {
-      // feed import failed
-      $resp = "Error fetching feed, response code: " . $result->getHttpCode();
-    }
-    return $resp;
-  }
 }

Added: incubator/shindig/trunk/php/src/gadgets/MakeRequestOptions.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/MakeRequestOptions.php?rev=811651&view=auto
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/MakeRequestOptions.php (added)
+++ incubator/shindig/trunk/php/src/gadgets/MakeRequestOptions.php Sat Sep  5 14:18:27 2009
@@ -0,0 +1,694 @@
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * Exception class thrown when a paramter is incorrectly configured on the
+ * MakeRequestOptions class.
+ */
+class MakeRequestParameterException extends Exception {}
+
+/**
+ * Class that manages the configuration of a makeRequest fetch call.
+ * Example - initializing a feed fetch manually:
+ * <code>
+ *   $context = new GadgetContext('GADGET');
+ *   $params = new MakeRequestOptions('http://www.example.com');
+ *   $params->setResponseFormat('FEED')
+ *          ->setNoCache(true)
+ *          ->setNumEntries(10)
+ *          ->setGetSummaries(true));
+ *   $result = $this->makeRequest->fetch($context, $params);
+ * </code>
+ *
+ * Additionally, this class can configure itself from the current HTTP request
+ * (useful in a servlet).  Example:
+ * <code>
+ *   $context = new GadgetContext('GADGET');
+ *   $params = MakeRequestOptions::fromCurrentRequest();
+ *   $result = $this->makeRequest->fetch($context, $params);
+ * </code>
+ */
+class MakeRequestOptions {
+  const DEFAULT_REFRESH_INTERVAL = 3600;
+  const DEFAULT_HTTP_METHOD = 'GET';
+  const DEFAULT_OUTPUT_FORMAT = 'JSON';
+  const DEFAULT_AUTHZ = 'NONE';
+  const DEFAULT_SIGN_VIEWER = true;
+  const DEFAULT_SIGN_OWNER = true;
+  const DEFAULT_OAUTH_USE_TOKEN = 'IF_AVAILABLE';
+  const DEFAULT_NUM_ENTRIES = 3;
+  const DEFAULT_GET_SUMMARIES = false;
+
+  static $VALID_HTTP_METHODS = array('GET', 'PUT', 'POST', 'HEAD', 'DELETE');
+  static $VALID_OUTPUT_FORMATS = array('TEXT', 'JSON', 'FEED');
+  static $VALID_AUTHZ = array('OAUTH', 'NONE', 'SIGNED');
+  static $VALID_OAUTH_USE_TOKEN = array('NEVER', 'IF_AVAILABLE', 'ALWAYS');
+
+  private $href;
+  private $method;
+  private $body;
+  private $headers;
+  private $format;
+  private $authz;
+  private $signViewer;
+  private $signOwner;
+  private $oauthServiceName;
+  private $oauthTokenName;
+  private $oauthRequestToken;
+  private $oauthRequestTokenSecret;
+  private $oauthUseToken;
+  private $oauthClientState;
+  private $noCache;
+  private $refreshInterval;
+  private $numEntries;
+  private $getSummaries;
+  private $st;
+
+  /**
+   * Constructor.
+   *
+   * @param string $href Url to fetch.
+   */
+  public function __construct($href) {
+    $this->href = MakeRequestOptions::validateUrl($href);
+  }
+
+  /**
+   * Throws an exception if the supplied parameter is not in a set of values.
+   *
+   * @param mixed $param Parameter to check.
+   * @param array $values Valid values.
+   * @return mixed The value if the parameter exists in the array.  If a
+   *     string is passed, the string is set to uppercase before being checked
+   *     against the array and returned as an uppercase string.
+   * @throws MakeRequestParameterException If the value was not found in the
+   *     array.
+   */
+  private function assertParameterIsOneOf($param, $values) {
+    if (is_string($param)) {
+      $param = strtoupper($param);
+    }
+    if (!in_array($param, $values)) {
+      throw new MakeRequestParameterException($name . " parameter must be one of " . implode(', ', $values));
+    }
+    return $param;
+  }
+
+  /**
+   * Validates that a passed in argument is actually an url.
+   *
+   * @param string $url The parameter to check.
+   * @return string The url if it can be parsed as an url.
+   * @throws MakeRequestParameterException If the url could not be parsed.
+   */
+  public static function validateUrl($url) {
+    if (empty($url) || !@parse_url($url)) {
+      throw new MakeRequestParameterException("Invalid Url");
+    } else {
+      return $url;
+    }
+  }
+
+  /**
+   * Attempts to pull the requested parameter from the current HTTP request
+   * and return it.  If a type is specified and the requests contains a
+   * parameter with the specified name, the value of the parameter is attempted
+   * to be coerced to the requested type.  PHP's settype is used to perform
+   * the cast, although a special case is considered for the string "false"
+   * which should evaluate to boolean false in the case of http requests.
+   *
+   * @param string $name The name of the parameter to check for.  This method
+   *     examines the $_GET superglobal first, then the $_POST.
+   * @param string $optType An optional name of a type to cerce to.  Check the
+   *     documentation for PHP's <code>settype</code> function to see valid
+   *     values for this parameter.
+   * @return mixed The value of the parameter, or null if it didn't exist.
+   * @throws MakeRequestParameterException If a type was specified and the
+   *     argument could not be converted to the correct type.
+   */
+  private static function getRequestParam($name, $optType = null) {
+    $param = null;
+    if (array_key_exists($name, $_GET)) {
+      $param = $_GET[$name];
+    } else if (array_key_exists($name, $_POST)) {
+      $param = $_POST[$name];
+    }
+    if (empty($param)) {
+      $param = null;
+    }
+    if (isset($param) && isset($optType)) {
+      switch (strtolower($optType)) {
+        case 'boolean':
+        case 'bool':
+          if (($param) === "false") {
+            $param = "0";
+          }
+      }
+      if (!settype($param, $optType)) {
+        throw new MakeRequestParameterException("Parameter '$name' should be convertable to $optType.");
+      }
+    }
+    return $param;
+  }
+
+  /**
+   * Builds a MakeRequestOptions object from the current $_GET and $_POST
+   * superglobals.
+   *
+   * @return MakeRequestOptions An object initialized from the current request.
+   * @throws MakeRequestParameterException If any of the parameters were
+   *     invalid.
+   */
+  public static function fromCurrentRequest(){
+    $href = MakeRequestOptions::getRequestParam('href');
+    if (!isset($href)) {
+      $href = MakeRequestOptions::getRequestParam('url');
+    }
+
+    $options = new MakeRequestOptions($href);
+    $options->setHttpMethod(MakeRequestOptions::getRequestParam('httpMethod'))
+            ->setRequestBody(MakeRequestOptions::getRequestParam('postData'))
+            ->setFormEncodedRequestHeaders(MakeRequestOptions::getRequestParam('headers'))
+            ->setResponseFormat(MakeRequestOptions::getRequestParam('contentType'))
+            ->setAuthz(MakeRequestOptions::getRequestParam('authz'))
+            ->setSignViewer(MakeRequestOptions::getRequestParam('signViewer', 'boolean'))
+            ->setSignOwner(MakeRequestOptions::getRequestParam('signOwner', 'boolean'))
+            ->setNumEntries(MakeRequestOptions::getRequestParam('numEntries', 'integer'))
+            ->setGetSummaries(MakeRequestOptions::getRequestParam('getSummaries', 'boolean'))
+            ->setRefreshInterval(MakeRequestOptions::getRequestParam('refreshInterval', 'integer'))
+            ->setNoCache(MakeRequestOptions::getRequestParam('bypassSpecCache', 'boolean'))
+            ->setOAuthServiceName(MakeRequestOptions::getRequestParam('OAUTH_SERVICE_NAME'))
+            ->setOAuthTokenName(MakeRequestOptions::getRequestParam('OAUTH_TOKEN_NAME'))
+            ->setOAuthRequestToken(MakeRequestOptions::getRequestParam('OAUTH_REQUEST_TOKEN'))
+            ->setOAuthRequestTokenSecret(MakeRequestOptions::getRequestParam('OAUTH_REQUEST_TOKEN_SECRET'))
+            ->setOAuthUseToken(MakeRequestOptions::getRequestParam('OAUTH_USE_TOKEN'))
+            ->setOAuthClientState(MakeRequestOptions::getRequestParam('oauthState'))
+            ->setSecurityTokenString(MakeRequestOptions::getRequestParam('st'));
+            
+    return $options;
+  }
+
+  /**
+   * Gets the configured URL.
+   *
+   * @return string The value of this parameter.
+   */
+  public function getHref() {
+    return $this->href;
+  }
+
+  /**
+   * Sets the http method to use for this request.  Must be one of
+   * {@link MakeRequestOptions::$VALID_HTTP_METHODS}.
+   *
+   * @param string $method The value to use.
+   * @return MakeRequestOptions This object (for chaining purporses).
+   */
+  public function setHttpMethod($method) {
+    if (isset($method)) {
+      $this->method = $this->assertParameterIsOneOf($method, MakeRequestOptions::$VALID_HTTP_METHODS);
+    }
+    return $this;
+  }
+
+  /**
+   * Gets the configured HTTP method.
+   *
+   * @return string The value of this parameter.
+   */
+  public function getHttpMethod() {
+    return isset($this->method) ? $this->method : MakeRequestOptions::DEFAULT_HTTP_METHOD;
+  }
+
+  /**
+   * Sets the request body.
+   *
+   * @param string $body The value to use.
+   * @return MakeRequestOptions This object (for chaining purporses).
+   */
+  public function setRequestBody($body) {
+    if (isset($body)) {
+      $this->body = $body;
+    }
+    return $this;
+  }
+
+  public function getRequestBody() {
+    return isset($this->body) ? $this->body : null;
+  }
+
+  /**
+   * Sets the headers to use when making the request.
+   *
+   * @param array $headers An array of key/value pairs to use as HTTP headers.
+   *     Example:
+   *     <code>
+   *     $params->setRequestHeaders(array(
+   *         'Content-Type' => 'text/plain',
+   *         'Accept-Language' => 'en-us'
+   *     ));
+   *     </code>
+   * @return MakeRequestOptions This object (for chaining purporses).
+   */
+  public function setRequestHeaders(array $headers) {
+    if (isset($headers)) {
+      $this->headers = $headers;
+    }
+    return $this;
+  }
+
+  /**
+   * Sets the headers to use when making the request.
+   *
+   * @param string $headers A form-urlencoded string of key/values to use as
+   *     HTTP headers for the request.  The OpenSocial JavaScript library
+   *     passes makeRequest headers in this format, so this is just a
+   *     convenience method.
+   *     Example:
+   *     <code>
+   *     $params->setFormEncodedRequestHeaders(
+   *       "Content-Type=text/plain&Accept-Language=en-us"
+   *     );
+   *     </code>
+   * @return MakeRequestOptions This object (for chaining purporses).
+   */
+  public function setFormEncodedRequestHeaders($headers) {
+    if (isset($headers)) {
+      $headerLines = explode("&", $headers);
+      $this->headers = array();
+      foreach ($headerLines as $line) {
+        $parts = explode("=", $line);
+        if (count($parts) == 2) {
+          $this->headers[urldecode($parts[0])] = urldecode($parts[1]);
+        }
+      }
+    }
+    return $this;
+  }
+
+  /**
+   * Gets the configured request headers in the HTTP header format (separated
+   * by newlines, with a key-colon-space-value format).  Example:
+   * <code>
+   *   Content-Type: text/plain
+   *   Accept-Language: en-us
+   * </code>
+   *
+   * @return string The value of this parameter.
+   */
+  public function getFormattedRequestHeaders() {
+    if (isset($this->headers)) {
+      $headerString = http_build_query($this->headers);
+      return urldecode(str_replace("&", "\n", str_replace("=", ": ", $headerString)));
+    } else {
+      return false;
+    }
+  }
+
+  /**
+   * Sets the expected response format for this type of request.  Valid values
+   * are one of {@link MakeRequestOptions::$VALID_OUTPUT_FORMATS}.
+   *
+   * @param string $format The value to use.
+   * @return MakeRequestOptions This object (for chaining purporses).
+   */
+  public function setResponseFormat($format) {
+    if (isset($format)) {
+      $this->format = $this->assertParameterIsOneOf($format, MakeRequestOptions::$VALID_OUTPUT_FORMATS);
+    }
+    return $this;
+  }
+
+  /**
+   * Gets the configured response format.
+   *
+   * @return string The value of this parameter.
+   */
+  public function getResponseFormat() {
+    return isset($this->format) ? $this->format : MakeRequestOptions::DEFAULT_OUTPUT_FORMAT;
+  }
+
+  /**
+   * Sets the authorization type of the request.  Must be one of
+   * {@link MakeRequestOptions::$VALID_AUTHZ}.
+   * 
+   * @param string $authz The value to use.
+   * @return MakeRequestOptions This object (for chaining purporses).
+   */
+  public function setAuthz($authz) {
+    if (isset($authz)) {
+      $this->authz = $this->assertParameterIsOneOf($authz, MakeRequestOptions::$VALID_AUTHZ);
+    }
+    return $this;
+  }
+
+  /**
+   * Gets the configured authz parameter.
+   *
+   * @return string The value of this parameter.
+   */
+  public function getAuthz() {
+    return isset($this->authz) ? $this->authz : MakeRequestOptions::DEFAULT_AUTHZ;
+  }
+
+  /**
+   * Sets whether to include the viewer's ID in a signed request.
+   *
+   * @param bool $signViewer True to include the viewer's ID.
+   * @return MakeRequestOptions This object (for chaining purporses).
+   */
+  public function setSignViewer($signViewer) {
+    if (isset($signViewer)) {
+      if (!is_bool($signViewer)) {
+        throw new MakeRequestParameterException("signViewer must be a boolean.");
+      }
+      $this->signViewer = $signViewer;
+    }
+    return $this;
+  }
+
+  /**
+   * Gets the configured value of whether to sign with the viewer ID or not.
+   *
+   * @return string The value of this parameter.
+   */
+  public function getSignViewer() {
+    return isset($this->signViewer) ? $this->signViewer : MakeRequestOptions::DEFAULT_SIGN_VIEWER;
+  }
+
+  /**
+   * Sets whether to include the owner's ID in a signed request.
+   *
+   * @param bool $signOwner True to include the owner's ID.
+   * @return MakeRequestOptions This object (for chaining purporses).
+   */
+  public function setSignOwner($signOwner) {
+    if (isset($signOwner)) {
+      if (!is_bool($signOwner)) {
+        throw new MakeRequestParameterException("signOwner must be a boolean.");
+      }
+      $this->signOwner = $signOwner;
+    }
+    return $this;
+  }
+
+  /**
+   * Gets the configured value of whether to sign with the owner ID or not.
+   *
+   * @return string The value of this parameter.
+   */
+  public function getSignOwner() {
+    return isset($this->signOwner) ? $this->signOwner : MakeRequestOptions::DEFAULT_SIGN_OWNER;
+  }
+
+  /**
+   * Sets the OAuth service name.
+   *
+   * @param string $serviceName The value to use.
+   * @return MakeRequestOptions This object (for chaining purporses).
+   */
+  public function setOAuthServiceName($serviceName) {
+    if (isset($serviceName)) {
+      $this->oauthServiceName = $serviceName;
+    }
+    return $this;
+  }
+
+  /**
+   * Gets the configured OAuth service name.
+   *
+   * @return string The value of this parameter.
+   */
+  public function getOAuthServiceName() {
+    return isset($this->oauthServiceName) ? $this->oauthServiceName : '';
+  }
+
+  /**
+   * Sets the OAuth token name.
+   *
+   * @param string $tokenName The value to use.
+   * @return MakeRequestOptions This object (for chaining purporses).
+   */
+  public function setOAuthTokenName($tokenName) {
+    if (isset($tokenName)) {
+      $this->oauthTokenName = $tokenName;
+    }
+    return $this;
+  }
+
+  /**
+   * Gets the configured OAuth token name.
+   *
+   * @return string The value of this parameter.
+   */
+  public function getOAuthTokenName() {
+    return isset($this->oauthTokenName) ? $this->oauthTokenName : '';
+  }
+
+  /**
+   * Sets the OAuth request token.
+   *
+   * @param string $requestToken The value to use.
+   * @return MakeRequestOptions This object (for chaining purporses).
+   */
+  public function setOAuthRequestToken($requestToken) {
+    if (isset($requestToken)) {
+      $this->oauthRequestToken = $requestToken;
+    }
+    return $this;
+  }
+
+  /**
+   * Gets the configured OAuth request token.
+   *
+   * @return string The value of this parameter.
+   */
+  public function getOAuthRequestToken() {
+    return isset($this->oauthRequestToken) ? $this->oauthRequestToken : '';
+  }
+
+  /**
+   * Sets the OAuth request token secret.
+   *
+   * @param string $requestTokenSecret The value to use.
+   * @return MakeRequestOptions This object (for chaining purporses).
+   */
+  public function setOAuthRequestTokenSecret($requestTokenSecret) {
+    if (isset($requestTokenSecret)) {
+      $this->oauthRequestTokenSecret = $requestTokenSecret;
+    }
+    return $this;
+  }
+
+  /**
+   * Gets the configured OAuth request token secret.
+   *
+   * @return string The value of this parameter.
+   */
+  public function getOAuthRequestTokenSecret() {
+    return isset($this->oauthRequestTokenSecret) ? $this->oauthRequestTokenSecret : '';
+  }
+
+  /**
+   * Sets whether to use an OAuth token.  Must be one of
+   * {@link MakeRequestOptions::$VALID_OAUTH_USE_TOKEN}.
+   *
+   * @param string $oauthUseToken The value to use.
+   * @return MakeRequestOptions This object (for chaining purporses).
+   */
+  public function setOAuthUseToken($oauthUseToken) {
+    if (isset($oauthUseToken)) {
+      $this->oauthUseToken = $this->assertParameterIsOneOf($oauthUseToken, MakeRequestOptions::$VALID_OAUTH_USE_TOKEN);
+    }
+    return $this;
+  }
+
+  /**
+   * Gets the configured value of whether to use the OAuth token.
+   *
+   * @return string The value of this parameter.
+   */
+  public function getOAuthUseToken() {
+    return isset($this->oauthUseToken) ? $this->oauthUseToken : MakeRequestOptions::DEFAULT_OAUTH_USE_TOKEN;
+  }
+
+  /**
+   * Sets the OAuth client state.
+   *
+   * @param string $oauthClientState The value to use.
+   * @return MakeRequestOptions This object (for chaining purporses).
+   */
+  public function setOAuthClientState($oauthClientState) {
+    if (isset($oauthClientState)) {
+      $this->oauthClientState = $oauthClientState;
+    }
+    return $this;
+  }
+
+  /**
+   * Gets the configured OAuth client state.
+   *
+   * @return string The value of this parameter.
+   */
+  public function getOAuthClientState() {
+    return isset($this->oauthClientState) ? $this->oauthClientState : null;
+  }
+
+  /**
+   * Gets all of the configured OAuth parameters as an OAuthRequestParams
+   * object.
+   *
+   * @return OAuthRequestParams The collection of OAuth parameters.
+   */
+  public function getOAuthRequestParameters() {
+    return new OAuthRequestParams(array(
+        OAuthRequestParams::SERVICE_PARAM => $this->getOAuthServiceName(),
+        OAuthRequestParams::TOKEN_PARAM => $this->getOAuthTokenName(),
+        OAuthRequestParams::REQUEST_TOKEN_PARAM => $this->getOAuthRequestToken(),
+        OAuthRequestParams::REQUEST_TOKEN_SECRET_PARAM => $this->getOAuthRequestTokenSecret(),
+        OAuthRequestParams::BYPASS_SPEC_CACHE_PARAM => $this->getNoCache(),
+        OAuthRequestParams::CLIENT_STATE_PARAM => $this->getOAuthClientState()
+    ));
+  }
+
+  /**
+   * Sets whether to bypass the cache for this request.
+   *
+   * @param bool $noCache True if the request should bypass the cache.
+   * @return MakeRequestOptions This object (for chaining purporses)
+   */
+  public function setNoCache($noCache) {
+    if (isset($noCache)) {
+      if (!is_bool($noCache)) {
+        throw new MakeRequestParameterException("noCache must be a boolean.");
+      }
+      $this->noCache = $noCache;
+    }
+    return $this;
+  }
+
+  /**
+   * Gets the configured value of whether to bypass the cache.
+   *
+   * @return string The value of this parameter.
+   */
+  public function getNoCache() {
+    return isset($this->noCache) ? $this->noCache : false;
+  }
+
+  /**
+   * Sets the refresh interval for this request.  Must be an integer equal to
+   * or greater than 0.
+   *
+   * @param int $refreshInterval The value to use
+   * @return MakeRequestOptions This object (for chaining purporses)
+   */
+  public function setRefreshInterval($refreshInterval) {
+    if (isset($refreshInterval)) {
+      if (!is_int($refreshInterval) || $refreshInterval < 0) {
+        throw new MakeRequestParameterException('Refresh interval must be greater than or equal to 0');
+      }
+      $this->refreshInterval = $refreshInterval;
+    }
+    return $this;
+  }
+
+  /**
+   * Gets the configured refresh interval.
+   *
+   * @return string The value of this parameter.
+   */
+  public function getRefreshInterval() {
+    return isset($this->refreshInterval) ? $this->refreshInterval : MakeRequestOptions::DEFAULT_REFRESH_INTERVAL;
+  }
+
+  /**
+   * Sets the number of entries to return for format = FEED requests.  Must
+   * be an integer greater than 0.
+   *
+   * @param int $numEntries The value to use
+   * @return MakeRequestOptions This object (for chaining purporses)
+   */
+  public function setNumEntries($numEntries) {
+    if (isset($numEntries)) {
+      if (!is_int($numEntries) || $numEntries <= 0) {
+        throw new MakeRequestParameterException('NumEntries must be greater than 0');
+      }
+      $this->numEntries = $numEntries;
+    }
+    return $this;
+  }
+
+  /**
+   * Gets the configured number of entries to return for a feed request.
+   *
+   * @return string The value of this parameter.
+   */
+  public function getNumEntries() {
+    return isset($this->numEntries) ? $this->numEntries : MakeRequestOptions::DEFAULT_NUM_ENTRIES;
+  }
+
+  /**
+   * Sets whether to fetch summaries for format = FEED requests.
+   *
+   * @param bool $getSummaries The value to use
+   * @return MakeRequestOptions This object (for chaining purporses)
+   */
+  public function setGetSummaries($getSummaries) {
+    if (isset($getSummaries)) {
+      if (!is_bool($getSummaries)) {
+        throw new MakeRequestParameterException("getSummaries must be a boolean.");
+      }
+      $this->getSummaries = $getSummaries;
+    }
+    return $this;
+  }
+
+  /**
+   * Gets the configured value of whether to fetch summaries for a feed request.
+   *
+   * @return string The value of this parameter.
+   */
+  public function getGetSummaries() {
+    return isset($this->getSummaries) ? $this->getSummaries : MakeRequestOptions::DEFAULT_GET_SUMMARIES;
+  }
+
+  /**
+   * Sets a security token string.  Required for signed or OAuth requests.
+   *
+   * @param string $st The value to use
+   * @return MakeRequestOptions This object (for chaining purporses)
+   */
+  public function setSecurityTokenString($st) {
+    if (isset($st)) {
+      $this->st = $st;
+    }
+    return $this;
+  }
+
+  /**
+   * Gets the configured security token string.
+   *
+   * @return string The value of this parameter.
+   */
+  public function getSecurityTokenString() {
+    return isset($this->st) ? $this->st : false;
+  }
+}
\ No newline at end of file

Modified: incubator/shindig/trunk/php/src/gadgets/ProxyBase.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/ProxyBase.php?rev=811651&r1=811650&r2=811651&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/ProxyBase.php (original)
+++ incubator/shindig/trunk/php/src/gadgets/ProxyBase.php Sat Sep  5 14:18:27 2009
@@ -18,6 +18,8 @@
  * under the License.
  */
 
+require_once 'src/gadgets/MakeRequest.php';
+
 /**
  * This class contains the shared methods between the Proxy and makeRequest handlers
  */
@@ -27,10 +29,13 @@
    */
   public $context;
 
-  protected $disallowedHeaders = array('User-Agent', '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');
+  protected $disallowedHeaders = array('User-Agent', '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');
 
   public function __construct($context) {
     $this->context = $context;
+    $this->makeRequest = new MakeRequest();
   }
 
   /**
@@ -42,43 +47,18 @@
    * @return RemoteContentRequest the filled in request (RemoteContentRequest)
    */
   protected function buildRequest($url, $method = 'GET', $signer = null) {
-    // Check the protocol requested - curl doesn't really support file://
-    // requests but the 'error' should be handled properly
-    $protocolSplit = explode('://', $url, 2);
-    if (count($protocolSplit) < 2) {
-      throw new Exception("Invalid protocol specified");
-    } else {
-      $protocol = strtoupper($protocolSplit[0]);
-      if ($protocol != "HTTP" && $protocol != "HTTPS") {
-        throw new Exception("Invalid protocol specified in url: " . htmlentities($protocol));
-      }
-    }
-    if ($method == 'POST') {
-      $postData = isset($_GET['postData']) ? $_GET['postData'] : (isset($_POST['postData']) ? $_POST['postData'] : false);
-      // even if postData is an empty string, it will still post (since RemoteContentRquest checks if its false)
-      // so the request to POST is still honored
-      $request = new RemoteContentRequest($url, null, $postData);
-    } else {
-      $request = new RemoteContentRequest($url);
-    }
-    if ($signer) {
-      $authz = isset($_GET['authz']) ? $_GET['authz'] : (isset($_POST['authz']) ? $_POST['authz'] : '');
-      switch (strtoupper($authz)) {
-        case 'SIGNED':
-          $request->setAuthType(RemoteContentRequest::$AUTH_SIGNED);
-          break;
-        case 'OAUTH':
-          $request->setAuthType(RemoteContentRequest::$AUTH_OAUTH);
-          $request->setOAuthRequestParams(new OAuthRequestParams($_REQUEST));
-          break;
-      }
-      $token = $this->context->extractAndValidateToken($signer);
-      $request->setToken($token);
-    }
-    if (isset($_POST['headers'])) {
-      $request->setHeaders(urldecode(str_replace("&", "\n", str_replace("=", ": ", $_POST['headers']))));
-    }
-    return $request;
+    // TODO: Check to see if we can just use MakeRequestOptions::fromCurrentRequest
+    $st = isset($_GET['st']) ? $_GET['st'] : (isset($_POST['st']) ? $_POST['st'] : false);
+    $body = isset($_GET['postData']) ? $_GET['postData'] : (isset($_POST['postData']) ? $_POST['postData'] : false);
+    $authz = isset($_GET['authz']) ? $_GET['authz'] : (isset($_POST['authz']) ? $_POST['authz'] : '');
+    $headers = isset($_GET['headers']) ? $_GET['headers'] : (isset($_POST['headers']) ? $_POST['headers'] : '');
+    $params = new MakeRequestOptions($url);
+    $params->setSecurityTokenString($st)
+      ->setAuthz($authz)
+      ->setRequestBody($body)
+      ->setHttpMethod($method)
+      ->setFormEncodedRequestHeaders($headers);
+    return $this->makeRequest->buildRequest($this->context, $params, $signer);
   }
 
   /**
@@ -111,11 +91,7 @@
    * @return string the 'validated' url
    */
   protected function validateUrl($url) {
-    if (! @parse_url($url)) {
-      throw new Exception("Invalid Url");
-    } else {
-      return $url;
-    }
+    return MakeRequestOptions::validateUrl($url);
   }
 
   /**

Modified: incubator/shindig/trunk/php/src/gadgets/servlet/MakeRequestServlet.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/servlet/MakeRequestServlet.php?rev=811651&r1=811650&r2=811651&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/servlet/MakeRequestServlet.php (original)
+++ incubator/shindig/trunk/php/src/gadgets/servlet/MakeRequestServlet.php Sat Sep  5 14:18:27 2009
@@ -35,24 +35,17 @@
     try {
       $this->noHeaders = true;
       $context = new GadgetContext('GADGET');
-      $url = isset($_GET['url']) ? $_GET['url'] : (isset($_POST['url']) ? $_POST['url'] : false);
-      if (! $url || empty($url)) {
-        header("HTTP/1.0 400 Bad Request", true);
-        echo "<html><body><h1>400 - Missing url parameter</h1></body></html>";
-      }
-      $method = (isset($_GET['httpMethod']) ? $_GET['httpMethod'] : (isset($_POST['httpMethod']) ? $_POST['httpMethod'] : 'GET'));
-      $signingFetcherFactory = $gadgetSigner = false;
-      if (! empty($_GET['authz']) || ! empty($_POST['authz'])) {
-        $gadgetSigner = Config::get('security_token_signer');
-        $gadgetSigner = new $gadgetSigner();
-        $signingFetcherFactory = new SigningFetcherFactory(Config::get("private_key_file"));
-      }
-      $makeRequestHandler = new MakeRequestHandler($context, $signingFetcherFactory);
-      $makeRequestHandler->fetchJson($url, $gadgetSigner, $method);
+      $makeRequestParams = MakeRequestOptions::fromCurrentRequest();
+      $makeRequestHandler = new MakeRequestHandler($context);
+      $makeRequestHandler->fetchJson($makeRequestParams);
+    } catch (MakeRequestParameterException $e) {
+      // Something was misconfigured in the request
+      header("HTTP/1.0 400 Bad Request", true);
+      echo "<html><body><h1>400 - Bad request</h1><p>" . $e->getMessage() . "</body></html>";
     } catch (Exception $e) {
       // catch all exceptions and give a 500 server error
       header("HTTP/1.0 500 Internal Server Error");
-      echo "<h1>Internal server error</h1><p>" . $e->getMessage() . "</p>";
+      echo "<html><body><h1>Internal server error</h1><p>" . $e->getMessage() . "</p></body></html>";
     }
   }