f3acd66
click here to add a description
click here to add a homepage
RESTful resource/url mapping and MVC, featuring Request an Response objects. — Read more
http://www.phpclasses.org/browse/package/5080.html
This URL has Read+Write access
Bugs fixes and Authenticator done for Basic and Digest, and phpdocs
@@ -11,8 +11,8 @@ class GenericView implements RestView {
/**
* Constructor of GenericView
- * @param $file=null , The script to be rendered
- * @param $props=null , Vars to be passed to the script
+ * @param string $file The script to be rendered
+ * @param mixed $props Vars to be passed to the script
*/
function __construct($file=null,$props=null) {
if($file != null) $this->file = $file ;
@@ -1,7 +1,7 @@
<?php
* Class RestAction
- * Inteface for a possible action for to be taken
+ * Inteface for a possible action for to be taken by RestServer
interface RestAction {
@@ -0,0 +1,242 @@
+<?php
+
+include_once 'RestServer.class.php';
+/**
+ * Class RestAuthenticator
+ * Responsible for dealing with both Basic and Digest authentication
+ */
+class RestAuthenticator {
+ private $rest ;
+ private $user ;
+ private $pwd ;
+ private $authData ;
+ private $isDigest =false;
+ private $requireAuth =false;
+ /**
+ * RestAuthenticator constructor
+ * @param RestServer $rest
+ public function __construct(RestServer $rest=null) {
+ $this->rest = $rest ;
+ if(isset($_SERVER['PHP_AUTH_DIGEST']))
+ $this->authData = $_SERVER['PHP_AUTH_DIGEST'] ;
+ if(isset($_SERVER['PHP_AUTH_USER']))
+ $this->user = $_SERVER["PHP_AUTH_USER"];
+ if(isset($_SERVER['PHP_AUTH_PW']))
+ $this->pwd = $_SERVER["PHP_AUTH_PW"];
+ if(isset($_SERVER["HTTP_AUTHORIZATION"])) {
+ $base = base64_decode(substr($_SERVER["HTTP_AUTHORIZATION"],6));
+ $arr = explode(":",$base);
+ $this->user = $arr[0];
+ $this->pwd = $arr[1];
+ }
+ if (!empty($this->authData) && ($data = $this->digestParse($this->authData)) && $data['username']) {
+ $this->user = $data['username'] ;
+ $this->pwd = $data['response'] ;
+ * Return internal RestServer
+ * Return RestServer used;
+ * @return RestServer
+ public function getRest() {
+ return $this->rest;
+ * Return user sent on BASIC Authentication
+ * @return string
+ public function getUser() {
+ return $this->user;
+ * Return password sent for Authentication
+ public function getPassword() {
+ return $this->pwd ;
+ * Return if is using digest authentication
+ * @return bool
+ public function isDigest() {
+ return $this->isDigest ;
+ * Set if authentication should be Digest(true)
+ * @param bool $bool
+ * @param string $realm
+ * @return RestAuthenticator
+ public function forceDigest($bool=true,$realm=null) {
+ if($realm != null) $this->setRealm($realm);
+ $this->isDigest = $bool;
+ if($bool) {$this->requireAuthentication(true);}
+ return $this;
+ * Get the http Realm name
+ * @return string $realm
+ public function getRealm() {
+ return $this->realm;
+ * Set the http Realm name
+ public function setRealm($realm) {
+ $this->realm = $realm ;
+ * Sets if authentication is required
+ * @param bool $isRequered
+ public function requireAuthentication($isRequired=true) {
+ if($bol !== null) $this->requireAuth = $isRequired ;
+ return $this ;
+ * Checks if authenticated is required
+ * @return bool $auth;
+ public function isAuthenticationRequired() {
+ return $this->requireAuth ;
+ * Checks if is authenticated
+ public function isAuthenticated() {
+ return $this->auth ;
+ * Sets authentication status
+ * @param bool $auth Status
+ public function setAuthenticated($bool) {
+ $this->auth = $bool;
+ * Test if user is authenticated, and set proper headers if not
+ public function tryAuthenticate() {
+ if($this->isAuthenticationRequired() === false) return true;
+ if($this->isAuthenticated() == false) {
+ $this->getRest()->getResponse()->cleanHeader();
+ $this->getRest()->getResponse()->addHeader("HTTP/1.1 401 Unauthorized");
+ if($this->isDigest()) {
+ $this->getRest()->getResponse()->addHeader('WWW-Authenticate: Digest ' . $this->digestHeader());
+ } else {
+ $this->getRest()->getResponse()->addHeader('WWW-Authenticate: Basic realm="'.$this->getRealm().'"');
+ $this->getRest()->getResponse()->setResponse("Unauthorized");
+ return false ;
+ return true ;
+ * Test authentication against password for given username in Digest
+ * @param string $user
+ * @param string $password
+ public function validate($user,$password) {
+ $data = $this->digestParse($this->authData);
+ $A1 = md5($this->getUser() . ':' . $this->getRealm() . ':' . $password);
+ $A2 = md5($_SERVER['REQUEST_METHOD'].':'.$_SERVER['REQUEST_URI']);
+ $response = md5($A1.':'.$data['nonce'].':'.$data['nc'].':'.$data['cnonce'].':'.$data['qop'].':'.$A2);
+ if($this->getUser() === $user && $this->getPassword() === $response) {
+ $this->pwd = $password ;
+ $this->setAuthenticated(true);
+ $this->setAuthenticated(false);
+ if($this->getUser() === $user && $this->getPassword() === $password) {
+ * Parse the digest auth message
+ * @param string $message
+ * @return mixed
+ private function digestParse($txt) {
+ $needed_parts = array('nonce'=>1, 'nc'=>1, 'cnonce'=>1, 'qop'=>1, 'username'=>1, 'uri'=>1, 'response'=>1);
+ $data = array();
+ $parts = explode(",",$txt);
+ foreach($parts as $part) {
+ $div = strpos($part,"=");
+ $name = trim(substr($part,0,$div));
+ $value = trim(substr($part,$div + 1));
+ if($value[0] == "\"") {
+ $value = substr($value,1, strlen($value) - 2);
+ unset($needed_parts[$name]);
+ $data[$name] = $value;
+ return $needed_parts ? false : $data;
+ * Digest header
+ private function digestHeader() {
+ $op = array(
+ 'realm' => $this->getRealm(),
+ 'domain' => '/',
+ 'qop' => 'auth',
+ 'algorithm' => 'MD5',
+ 'nonce' => uniqid(),
+ 'opaque' => md5($this->getRealm()),
+ );
+ $str = 'realm="'.$op['realm'].'",';
+ $str .= 'qop="'.$op['qop'].'",';
+ $str .= 'nonce="'.$op['nonce'].'",';
+ $str .= 'opaque="'.$op['opaque'].'"';
+ return $str;
+}
+?>
@@ -25,7 +25,7 @@ class RestClient {
curl_setopt($this->curl,CURLOPT_RETURNTRANSFER,true);
curl_setopt($this->curl,CURLOPT_AUTOREFERER,true); // This make sure will follow redirects
curl_setopt($this->curl,CURLOPT_FOLLOWLOCATION,true); // This too
- curl_setopt($this->curl,CURLOPT_HEADER,true); // THis verbose option for extracting the headers
+ curl_setopt($this->curl,CURLOPT_HEADER,true); // This verbose option for extracting the headers
}
@@ -33,9 +33,19 @@ class RestClient {
* @return RestClient
public function execute() {
+ if($this->contentType != null) {
+ curl_setopt($this->curl,CURLOPT_HTTPHEADER,array("Content-Type: ".$this->contentType));
if($this->method === "POST") {
curl_setopt($this->curl,CURLOPT_POST,true);
- curl_setopt($this->curl,CURLOPT_POSTFIELDS,$this->params);
+ if(is_array($this->params)) {
+ foreach($this->params as $k=>$v) {
+ $params .= "$k=$v&";
+ $params = $this->params ;
+ curl_setopt($this->curl,CURLOPT_POSTFIELDS,$params);
} else if($this->method == "GET"){
curl_setopt($this->curl,CURLOPT_HTTPGET,true);
$this->treatURL();
@@ -50,9 +60,6 @@ class RestClient {
} else {
curl_setopt($this->curl,CURLOPT_CUSTOMREQUEST,$this->method);
- if($this->contentType != null) {
- curl_setopt($this->curl,CURLOPT_HTTPHEADER,array("Content-Type: ".$this->contentType));
- }
curl_setopt($this->curl,CURLOPT_URL,$this->url);
$r = curl_exec($this->curl);
$this->treatResponse($r); // Extract the headers and response
@@ -95,6 +102,9 @@ class RestClient {
$this->headers['message'] = $reg[2];
$this->response = "";
for($i=1;$i<count($parts);$i++) {//This make sure that exploded response get back togheter
+ if(($start = strpos($parts[$i],"\n")) !== false) {
+ $parts[$i] = substr($parts[$i],1);
if($i > 1) {
$this->response .= "\n\r";
@@ -103,6 +113,7 @@ class RestClient {
/*
+ * Array of headers
* @return array
public function getHeaders() {
@@ -110,6 +121,7 @@ class RestClient {
+ * Response body
* @return string
public function getResponse() {
@@ -223,7 +235,7 @@ class RestClient {
* Creates the RESTClient
- * @param string $url=null [optional]
+ * @param string $url
public static function createClient($url=null) {
@@ -237,51 +249,51 @@ class RestClient {
* Convenience method wrapping a commom POST call
* @param string $url
- * @param mixed params
- * @param string $user=null [optional]
- * @param string $password=null [optional]
- * @param string $contentType="multpary/form-data" [optional] commom post (multipart/form-data) as default
+ * @param mixed $params
+ * @param string $contentType
- public static function post($url,$params=null,$user=null,$pwd=null,$contentType="multipart/form-data") {
- return self::call("POST",$url,$params,$user,$pwd,$contentType);
+ public static function post($url,$params=null,$user=null,$password=null,$contentType="application/x-www-form-urlencoded") {
+ return self::call("POST",$url,$params,$user,$password,$contentType);
* Convenience method wrapping a commom PUT call
* @param string $body
- * @param string $contentType=null [optional]
- public static function put($url,$body,$user=null,$pwd=null,$contentType=null) {
- return self::call("PUT",$url,$body,$user,$pwd,$contentType);
+ public static function put($url,$body,$user=null,$password=null,$contentType=null) {
+ return self::call("PUT",$url,$body,$user,$password,$contentType);
* Convenience method wrapping a commom GET call
* @param array params
- public static function get($url,array $params=null,$user=null,$pwd=null) {
- return self::call("GET",$url,$params,$user,$pwd);
+ public static function get($url,array $params=null,$user=null,$password=null) {
+ return self::call("GET",$url,$params,$user,$password);
* Convenience method wrapping a commom delete call
- public static function delete($url,array $params=null,$user=null,$pwd=null) {
- return self::call("DELETE",$url,$params,$user,$pwd);
+ public static function delete($url,array $params=null,$user=null,$password=null) {
+ return self::call("DELETE",$url,$params,$user,$password);
@@ -289,16 +301,16 @@ class RestClient {
* @param string $method
- public static function call($method,$url,$body,$user=null,$pwd=null,$contentType=null) {
+ public static function call($method,$url,$body,$user=null,$password=null,$contentType=null) {
return self::createClient($url)
->setParameters($body)
->setMethod($method)
- ->setCredentials($user,$pwd)
+ ->setCredentials($user,$password)
->setContentType($contentType)
->execute()
->close();
@@ -9,7 +9,6 @@ interface RestController extends RestAction {
* Execute the Default action of this controller
* @param RestServer $restServer
* @return RestAction $restVieworController
- *
* */
function execute(RestServer $restServer) ;
@@ -9,110 +9,45 @@ class RestRequest {
private $requestURI ;
private $URIParts ;
-
- private $user ;
- private $pwd ;
- private $authData ;
- private $requestMethod ;
- private $get ;
- private $post ;
+ private $requestMethod ;
+ private $get ;
+ private $post ;
private $files ;
- * Constructor of RestRequest
- * @param RestServer $rest = null, Parent RestServer
- */
+ * Constructor of RestRequest
+ * @param RestServer $rest = null, Parent RestServer
public function __construct(RestServer $rest=null) {
// Sets most of the parameters
$this->rest = $rest ;
if(isset($_SERVER["REQUEST_METHOD"]))
$this->requestMethod = $_SERVER["REQUEST_METHOD"];
if(isset($_SERVER["REQUEST_URI"]))
$this->requestURI = $_SERVER["REQUEST_URI"];
$this->URIParts = explode("/",$this->requestURI);
- if(isset($_SERVER['PHP_AUTH_DIGEST']))
- $this->authData = $_SERVER['PHP_AUTH_DIGEST'] ;
- if(isset($_SERVER['PHP_AUTH_USER']))
- $this->user = $_SERVER["PHP_AUTH_USER"];
- if(isset($_SERVER['PHP_AUTH_PW']))
- $this->pwd = $_SERVER["PHP_AUTH_PW"];
- if(isset($_SERVER["HTTP_AUTHORIZATION"])) {
- $base = base64_decode(substr($_SERVER["HTTP_AUTHORIZATION"],6));
- $arr = explode(":",$base);
- $this->user = $arr[0];
- $this->pwd = $arr[1];
- $authData = $this->authData ;
- if (!empty($authData) && ($data = $this->digestParse($authData)) && $data['username']) {
- $this->user = $data['username'] ;
- $this->password = $data['response'] ;
+ $this->get = $_GET?$_GET:array() ;
+ $this->post = $_POST?$_POST:array() ;
+ $this->files = $_FILES?$_FILES:array() ;
- $this->get = $_GET ;
- $this->post = $_POST ;
- $this->files = $_FILES ;
- /**
- * Test authentication against password for given username in Digest authencitation
- * @param string $user
- * @param string $password
- * @return RestRequest
- public function validAuth($user,$password) {
- $bkp = $password;
- if($this->rest->isDigest()) {
- $A1 = md5($this->getUser() . ':' . $this->getRest()->getRealm() . ':' . $password);
- $A2 = md5($_SERVER['REQUEST_METHOD'].':'.$_SERVER['REQUEST_URI']);
- $password = md5($A1.':'.$data['nonce'].':'.$data['nc'].':'.$data['cnonce'].':'.$data['qop'].':'.$A2);
- if($this->getUser() === $user && $this->getPassword() === $password) {
- $this->getRest()->setAuth(true);
- $this->password = $password ;
- $this->password = $pwd ;
- return $this->getRest();
- * Return RestServer used;
- * @return RestServer
public function getRest() {
return $this->rest;
- private function digestParse($txt) {
- // protect against missing data
- $needed_parts = array('nonce'=>1, 'nc'=>1, 'cnonce'=>1, 'qop'=>1, 'username'=>1, 'uri'=>1, 'response'=>1);
- $data = array();
- // fix elements with missing "
- $txt = preg_replace('@=([^\'"])([^\s,]+)@', '="\1\2"', $txt);
- preg_match_all('@(\w+)=(?:([\'"])([^\2]+)\2|([^\s,]+))@U', $txt, $matches, PREG_SET_ORDER);
- foreach ($matches as $m) {
- $data[$m[1]] = trim($m[3] ? $m[3] : $m[4]);
- unset($needed_parts[$m[1]]);
- return $needed_parts ? false : $data;
- * Returns if Request is GET
- * @return boolean
+ * Returns if Request is GET
+ * @return boolean
public function isGet() {
if($this->requestMethod == "GET") {
return true ;
@@ -121,200 +56,200 @@ class RestRequest {
- * Returns if Request is POST
+ * Returns if Request is POST
public function isPost() {
- if($this->requestMethod == "POST") {
- return true ;
- return false;
+ if($this->requestMethod == "POST") {
+ return false;
- * Return if Request is PUT
+ * Return if Request is PUT
public function isPut() {
- if($this->requestMethod == "PUT") {
+ if($this->requestMethod == "PUT") {
- * Return true if Request is DELETE
+ * Return true if Request is DELETE
public function isDelete() {
- if($this->requestMethod == "DELETE") {
+ if($this->requestMethod == "DELETE") {
- * Get parameters sent with GET (url parameters)
- * @return array
+ * Get parameters sent with GET (url parameters)
+ * @param mixed $k get[$key]
public function getGet($k=null) {
if($k==null) return $this->get ;
else return $this->get[$k] ;
- * Return parameters sent on a POST
+ * Return parameters sent on a POST
+ * @param mixed $k post[$key]
public function getPost($k=null) {
if($k==null) return $this->post ;
else return $this->post[$k] ;
+ * Return FILES sent on a POSt
+ * @param mixed $k file[$key]
public function getFiles($k=null) {
if($k==null) return $this->files ;
else return $this->files[$k];
- * Return content sent with PUT
- * @param $key=null
- * @return mixed
+ * Return content sent with PUT
+ * @param mixed $k
public function getPut($k=null) {
- $_PUT = array();
- if($_SERVER['REQUEST_METHOD'] == 'PUT') {
- $putdata = file_get_contents('php://input');
- $exploded = explode('&', $putdata);
- foreach($exploded as $pair) {
- $item = explode('=', $pair);
- if(count($item) == 2) {
+ $_PUT = array();
+ if($_SERVER['REQUEST_METHOD'] == 'PUT') {
+ $putdata = file_get_contents('php://input');
+ $exploded = explode('&', $putdata);
+ foreach($exploded as $pair) {
+ $item = explode('=', $pair);
+ if(count($item) == 2) {
$_PUT[urldecode($item[0])] = urldecode($item[1]);
- if($k==null)return $_PUT ;
- else return $_PUT[$k];
+ if($k==null)return $_PUT ;
+ else return $_PUT[$k];
- * Return request BODY
- * @return string
+ * Return request BODY
public function getBody() {
- $data = file_get_contents('php://input');
- return $data;
+ $data = file_get_contents('php://input');
+ return $data;
- * Get authentication data on DIGEST
- public function getAuthData() {
- return $this->authData;
- * Return user sent on BASIC Authentication
- public function getUser() {
- return $this->user;
- * Return password sent on Basic Authentication
- public function getPassword() {
- return $this->pwd ;
- * Return Request Method(PUT, DELETE, OPTION, GET...)
- * return string
- public function getMethod() {
- return $this->requestMethod ;
- * Set request method
- * @param string $method
- public function setMethod($m) {
- $this->requestMethod = $m ;
- return $this;
- * Return the URI requested
- public function getRequestURI() {
- return $this->requestURI ;
- * Return part of the URL
- public function getURIpart($i) {
- if(isset($this->URIParts[$i]))
+ return $this->rest->getAuthenticator()->getUser();
+ * Return password sent on Basic Authentication
+ return $this->rest->getAuthenticator()->getPassword();
+ * Return Request Method(PUT, DELETE, OPTION, GET...)
+ public function getMethod() {
+ return $this->requestMethod ;
+ * Set request method
+ * @param string $method
+ * @return RestRequest
+ public function setMethod($method) {
+ $this->requestMethod = $method ;
+ * Return the URI requested
+ public function getRequestURI() {
+ return $this->requestURI ;
+ * Return part of the URL
+ * @param int $i part of the uri
+ public function getURIpart($i) {
+ if(isset($this->URIParts[$i]))
return $this->URIParts[$i];
else
return null;
- * Return the URI or part of it
- * @param $part=null, count of the part
- public function getURI($i=null) {
+ * Return the URI or part of it
+ public function getURI($i=null) {
if($i !== null) return $this->getURIpart($i);
return $this->getRequestURI() ;
- * Sets the URI to deal
- * @param string $uri
- * @return RestRequest $url
- public function setURI($url) {
- $this->requestURI = $url;
+ * Sets the URI to deal
+ * @param string $uri
+ public function setURI($uri) {
+ $this->requestURI = $uri;
return $this ;
- * Return the extension of the URI (if any)
- public function getExtension() {
- $reg = array();
- preg_match('@\.([a-zA-Z0-9]{1,5})$@',$this->rest->getQuery(),$reg);
- if(isset($reg[1]))
- return $reg[1];
- else
- * Return true if given mime is accepted
- * @param string $mime to check
- public function acceptMime($mime) {
- if(strpos($_SERVER["HTTP_ACCEPT"],$mime) > 0) {
+ * Return the extension of the URI (if any)
+ public function getExtension() {
+ $reg = array();
+ preg_match('@\.([a-zA-Z0-9]{1,5})$@',$this->getURI(),$reg);
+ if(isset($reg[1]))
+ return $reg[1];
+ else
+ * Return true if given mime is accepted
+ * @param string $mime to check
+ public function acceptMime($mime) {
+ if(($pos = strpos($_SERVER["HTTP_ACCEPT"],$mime)) !== false) {
return false ;
?>
@@ -8,87 +8,101 @@ class RestResponse {
private $headers ;
private $response ;
+ private $relm = "RESTful";
+ private $useDigest = false;
- * Constructor of RestServer
- * @param RestServer $rest
- function __contruct($rest=null) {
+ * Constructor of RestServer
+ public function __contruct(RestServer $rest=null) {
- * Set the response to null
- * @return RestResponse
- public function cleanResponse() {
- $this->response = null ;
- return $this ;
- * Adds a header to the response
- * @param string $header
- public function addHeader($header) {
+ * Adds a header to the response
+ * @param string $header
+ * @return RestResponse
+ public function addHeader($header) {
$this->headers[] = $header;
- * Clean the headers set on the response
- public function cleanHeader() {
+ * Clean the headers set on the response
+ public function cleanHeader() {
$this->headers = Array();
- * Show the headers
- public function showHeader() {
+ * Show the headers
+ public function showHeader() {
if(count($this->headers) >=1) {
foreach($this->headers as $value) {
header($value);
- * Check if headers were sent
- * @return bool
- public function headerSent() {
+ * Check if headers were sent
+ public function headerSent() {
return headers_sent();
- * Set the response
- * @param mixed $response
- public function setResponse($response) {
+ * Set the response
+ * @param mixed $response
+ public function setResponse($response) {
$this->response = $response ;
+ * Set the response to null
+ public function cleanResponse() {
+ $this->response = null ;
- * Add a string to the response, only work if response is a string
- * @param string $response
- public function addResponse($response) {
+ * Add a string to the response, only work if response is a string
+ * @param string $response
+ public function appendResponse($response) {
$this->response .= $response ;
+ public function addResponse($response) {
+ $this->response .= $response ;
- * Return the reponse set
- * @return mixed $response;
+ * Return the reponse set
+ * @return mixed $response;
return $this->response ;
@@ -1,327 +1,227 @@
include_once 'RestAction.class.php';
include_once 'RestController.class.php';
include_once 'RestView.class.php';
include_once 'RestRequest.class.php';
include_once 'RestResponse.class.php';
+include_once 'RestAuthenticator.class.php';
- * Class RestServer
- * Is the front controller for mapping URL to controllers and dealing with Request/Response and Headers
- * Made with Restful webservices in mind.
- * By Diogo Souza da Silva <manifesto@manifesto.blog.br>
+* Class RestServer
+* Is the front controller for mapping URL to controllers and dealing with Request/Response and Headers
+* Made with Restful webservices in mind.
+* By Diogo Souza da Silva <manifesto@manifesto.blog.br>
+*/
class RestServer {
- private $auth = true;
- private $requireAuth = false ;
- private $relm = "RESTful";
- private $useDigest = false;
- private $response ;
+ private $response ;
private $request ;
- private $headerOn = false ;
- private $baseUrl ;
- private $query ;
- private $qPart;
- private $map ;
+ private $authenticator ;
+ private $baseUrl ;
+ private $query ;
+ private $qPart;
+ private $map ;
private $params ;
private $stack ;
/** Contructor of RestServer
- * @param string $query Optional query to be treat as the URL
- * @return RestServer $rest;
+ * @param string $query Optional query to be treat as the URL
+ * @return RestServer $rest;
public function __construct($query=null) {
$this->request = new RestRequest($this); // Request handler
$this->response = new RestResponse($this); // Response holder
+ $this->authenticator = new RestAuthenticator($this); // Authenticator holder
if(isset($_SERVER["HTTP_HOST"]))
$this->baseUrl = "http://".$_SERVER["HTTP_HOST"].dirname($_SERVER["SCRIPT_NAME"]);
// If will use custom URI or HTTP requested URI
if($query===null) $this->query = $this->getRequest()->getRequestURI() ;
else $this->query = $query ;
$this->getRequest()->setURI($this->query);
- $this->qPart = explode("/",$this->query);
+ $this->qPart = explode("/",$this->query);
- * Sets a parameter in a global scope that can be recovered at any request.
- * @param mixed $key The identifier of the parameter
- * @param mixed $value The content of the parameter
- * @return RestServer $this
+ * Sets a parameter in a global scope that can be recovered at any request.
+ * @param mixed $key The identifier of the parameter
+ * @param mixed $value The content of the parameter
+ * @return RestServer $this
public function setParameter($key,$value) {
$this->params[$key] = $value ;
- * Return the specified parameter
- * @param mixed $key The parameter identifier
+ * Return the specified parameter
+ * @param mixed $key The parameter identifier
public function getParameter($key) {
return $this->params[$key];
- * Set the URL to be handle or part of it
- * @param mixed $value The url
- * @param int $key Optional, the part of the url to change
- public function setQuery($value,$k=null) {
- if($k !== null){
- $this->qPart[$k] = $value ;
- } else {
- $this->query = $value ;
- $this->qPart = explode("/",$value );
- * Maps a Method and URL for a Class
- * @param string $method The method to be associated
- * @param string $uri The URL to be accossiated
- * @param string $class The name of the class to be called, it must implement RestAction
- public function addMap($method,$uri,$class) {
- $this->map[$method][$uri] = $class ;
- * Checks if is authenticated
- * @return boolean $auth;
- public function isAuth() {
- return $this->auth ;
+ * Maps a Method and URL for a Class
+ * @param string $method The method to be associated
+ * @param string $uri The URL to be accossiated
+ * @param string $class The name of the class to be called, it must implement RestAction
+ public function addMap($method,$uri,$class) {
+ $this->map[$method][$uri] = $class ;
- * Sets authentication status
- * @param boolean $auth Status
- public function setAuth($bool) {
- $this->auth = $bool;
+ * Set the URL to be handle or part of it
+ * @param mixed $value The url
+ * @param int $k the part of the url to change
+ public function setQuery($value,$k=null) {
+ if($k !== null){
+ $this->qPart[$k] = $value ;
+ $this->query = $value ;
+ $this->qPart = explode("/",$value );
+ $this->getRequest()->setURI($value);
- * Get the URL or part of it, depreciated by RestRequest::getURI();
- **/
+ * Get the URL or part of it, depreciated by RestRequest::getURI();
+ * @param $k uri part
+ **/
public function getQuery($k=null) {
- return $this->qPart[$k];
+ return $this->qPart[$k];
return $this->query ;
- * Get the baseurl, based on website location (eg. localhost/website or website.com/);
- * @return string;
- public function getBaseUrl() {
+ * Get the baseurl, based on website location (eg. localhost/website or website.com/);
+ public function getBaseUrl() {
return $this->baseUrl ;
- * Get the Response handler object
- public function getResponse() {
+ * Get the Response handler object
+ public function getResponse() {
- /** Get the Request handler object
+ * Get the Request handler object
public function getRequest() {
return $this->request ;
- * Get the class for specified method and uri
- public function getMap($method,$uri) {
+ * Get the Authentication handler object
+ public function getAuthenticator() {
+ return $this->authenticator ;
+ * Get the class for specified method and uri
+ public function getMap($method,$uri) {
$maps = $this->map[$method];
if(count($maps) < 1) return false;
foreach($maps as $map=>$class) {
if(preg_match("%^".$map."$%",$uri) ) {
- return $class ;
+ return $class ;
- * Set if authentication should be Digest(true) or Basic(false)
- * @param booblean $useDigest
- public function useDigest($boolean=true) {
- $this->useDigest = $boolean;
- * return true if should use Digest authentication
- public function isDigest() {
- return $this->useDigest;
- * Get the http Realm name
- * @return string $realm
- public function getRealm() {
- return $this->realm;
- * Set the http Realm name
- * @param string $realm
- public function setRealm($realm) {
- $this->realm = $realm ;
- private function digestString() {
- $opt = array(
- 'realm' => $this->getRealm(),
- 'domain' => '/',
- 'qop' => 'auth',
- 'algorithm' => 'MD5',
- 'nonce' => uniqid(),
- 'opaque' => md5($this->getRealm()),
- );
- $str = 'realm="'.$op['realm'].'",';
- $str .= 'qop="'.$op['qop'].'",';
- $str .= 'nonce="'.$op['nonce'].'",';
- $str .= 'opaque="'.$op['opaque'].'"';
- return $str;
- * Unauthorize the request
- * $return RestServer
- public function unAuth() {
- $this->getResponse()->cleanHeader();
- $this->getResponse()->addHeader("HTTP/1.1 401 Unauthorized");
- if($this->useDigest) {
- $rest->getResponse()->addHeader('WWW-Authenticate: Digest ' . $this->digestString());
- $this->getResponse()->addHeader('WWW-Authenticate: Basic realm="'.$this->getRealm().'"');
- $this->getResponse()->setResponse("Unauthorized");
- private function testAuth() {
- if($this->requireAuth === false) return true;
- if(!$this->auth) {
- $this->unAuth();
- return false ;
- * Sets if authentication is required
- * @param boolean $isRequered Status to request, if null is given nothing changes
- * @return boolean if is required;
- public function requireAuth($bol=null) {
- if($bol !== null) $this->requireAuth = $bol ;
- return $this->requireAuth ;
- * Return last class name from RestServer stack trace
+ * Return last class name from RestServer stack trace
public function lastClass() {
$i = count($this->stack);
return $this->stack[$i - 1];
- * Run the Server to handle the request and prepare the response
- * @return string $responseContent
- public function execute() {
- if(!$this->testAuth()) return $this->show(); // If auth is required and its not ok, response is 401
+ * Run the Server to handle the request and prepare the response
+ * @return string $responseContent
+ public function execute() {
+ if(!$this->getAuthenticator()->tryAuthenticate()) {
+ return $this->show(); // If auth is required and its not ok, response is 401
// This is the class name to call
$responseClass = $this->getMap($this->getRequest()->getMethod(),$this->getQuery()) ;
+ $responseMethod = null;
if(!$responseClass) { // If no class was found, response is 404
$this->getResponse()->cleanHeader();
- $this->getResponse()->addHeader("HTTP/1.1 404 NOT FOUND");
+ $this->getResponse()->addHeader("HTTP/1.1 404 Not found");
$this->getResponse()->setResponse("HTTP/1.1 404 NOT FOUND");
return $this->show();
// In case a specific method should be called
- $parts = explode("::",$responseClass);
- if(isset($parts[0]))
+ if(count($parts = explode("::",$responseClass)) > 1) {
$responseClass = $parts[0];
- $responseClass = null ;
- if(isset($parts[1]))
$responseMethod = $parts[1];
- $responseMethod =null;
- $this->call(new $responseClass,$responseMethod); // Call the class
+ return $this->call(new $responseClass,$responseMethod)->show(); // Call the class and return the response
- return $this->show(); // Return response content
- private function call($class,$method=null) {
+ private function call($class,$method=null) {
$this->stack[] = get_class($class) ;
- if($class instanceof RestView) { // If is a view, call Show($restServer)
- if($method==null) $method="show";
- $class = $class->$method($this) ;
+ if($method != null) {
+ } else if($class instanceof RestView) { // If is a view, call Show($restServer)
+ $method="show";
} else if($class instanceof RestController) { //If is a controller, call execute($restServer)
- if($method==null) $method="execute";
- $class = $class->$method($this);
+ $method="execute";
+ Throw new Exception(get_class($class)." is not a RestAction");
+ $class = $class->$method($this);
if($class instanceof RestAction
- && get_class($class) != $this->lastClass() ) {
+ && get_class($class) != $this->lastClass() ) {
return $this->call($class); // May have another class to follow the request
- private function show() {
- $this->testAuth() ; // Test authentication
+ private function show() {
if(!$this->getResponse()->headerSent()) {
$this->getResponse()->showHeader(); // Call headers, if no yet
return $this->getResponse()->getResponse() ; // Return response content;
@@ -6,13 +6,12 @@ include_once 'RestAction.class.php';
* Interface describe a View for rendering an Response
interface RestView extends RestAction {
- * Render this view
- * Show($restServer)
- * @param RestServer $restServer
- * @return string HTML
- * */
- function show(RestServer $restServer) ;
+ * Render this view
+ * Show($restServer)
+ * @param RestServer $restServer
+ * */
+ function show(RestServer $restServer) ;
@@ -1,42 +0,0 @@
-<?php
-// dummy example of RestTest
-include '../RestClient.class.php';
-$twitter = RestClient::post( // Same for RestClient::get()
- "http://twitter.com/statuses/update.json"
- ,array("status"=>"Working with RestClient from RestServer!")
- ,"username"
- ,"password");
-var_dump($twitter->getResponse());
-var_dump($twitter->getResponseCode());
-var_dump($twitter->getResponseMessage());
-var_dump($twitter->getResponseContentType());
-// Other examples
-$url = "http://example";
-$user = "user";
-$password = "password";
-$ex = RestClient::get($url);
-$ex = RestClient::get($url,null,$user,$password);
-$ex = RestClient::get($url,array('key'=>'value'));
-$ex = RestClient::get($url,array('key'=>'value'),$user,$password);
-//content post
-$ex = RestClient::post($url);
-$ex = RestClient::post($url,null,$user,$password);
-$ex = RestClient::post($url,array('key'=>'value'));
-$ex = RestClient::post($url,array('key'=>'value'),$user,$password);
-$ex = RestClient::post($url,"some text",$user,$password,"text/plain");
-$ex = RestClient::post($url,"{ name: 'json'}",$user,$password,"application/json");
-$ex = RestClient::post($url,"<xml>Or any thing</xml>",$user,$password,"application/xml");
-// General cases
-$get = RestClient::get($url,array("q"=>"diogok.json","key"=>"value"),$user,$password);
-$post = RestClient::post($url,array("q"=>"diogok.json","key"=>"value"),$user,$password);
-$post = RestClient::post($url,"This is my json",$user,$password,"text/plain");
-$post = RestClient::post($url."?key=diogok","This is my json",$user,$password,"text/plain");
-$put = RestClient::put($url,"This is my json",$user,$password,"text/plain");
-$delete = RestClient::delete($url."?key=diogok",array("key"=>"value"),$user,$password);
-$http = RestClient::call("OPTIONS",$url."?key=diogok",array("key"=>"values"),$user,$password,"text/plain");
-?>
@@ -1,147 +0,0 @@
- include ("../RestServer.class.php");
- class RC implements RestController {
- function execute(RestServer $rest) {
- $rest->getResponse()->setResponse("Yahoo");
- return $rest ;
- function rock(RestServer $rest) {
- $rest->getResponse()->setResponse("We rock!");
- class RC2 implements RestController {
- return new view2();
- class view implements RestView {
- function show(RestServer $rest) {
- $rest->getResponse()->addResponse("Google");
- class view2 implements RestView {
- if($rest->getRequest()->getExtension() == "html") {
- $rest->getResponse()->setResponse("Its in HTML");
- $rest->getResponse()->setResponse("Plain Text");
- class RC3 implements RestController {
- $rest->getResponse()->setResponse("Finish!");
- return new RC3();
- $rest = new RestServer();
- $rest->getRequest()->setMethod("GET");
- $rest->addMap("POST","/user","RC");
- $rest->addMap("POST","/rock","RC::rock");
- $rest->addMap("POST","/user/([a-zA-Z0-9]*).?[a-zA-Z]{0,5}","RC2");
- $rest->addMap("GET","/user","view");
- $rest->addMap("GET","/rock","RC::rock");
- $rest->addMap("GET","/user/([a-zA-Z0-9]*).?[a-zA-Z]{0,5}","view2");
- $rest->addMap("GET","/error","RC3");
- $q = "/user.html";
- $rest->setQuery($q);
- if($rest->getQuery() != "/user.html") {
- echo "Failed at 1";
- return ;
- if($rest->getRequest()->getExtension() != "html") {
- echo "Failed at 2";
- $q = "/user";
- $response = $rest->execute() ;
- if($response != "Google") {
- echo "Failed at 75";
- $q = "/rock";
- if($response != "We rock!") {
- echo "Failed at 83";
- };
- $q = "/user/diogo";
- if($response != "Plain Text") {
- echo "Failed at 91";
- $q = "/user/diogo.html";
- if($response != "Its in HTML") {
- echo "Failed at 100";
- $rest->getRequest()->setMethod("POST");
- if($response != "Yahoo"){
- echo "Failed at 110";
- echo "Failed at 119";
- echo "Failed at 128";
- $q = "/error";
- if($response != "Finish!") {
- echo "Failed at 135";
-echo "PASSED\n";
-if(!function_exists("xdebug_time_index")) return ;
-echo "It took ".round(xdebug_time_index(),5)." seconds \n";
-echo "Used ".round(xdebug_memory_usage()/1024,5)."Kb of Memory\n";
-echo "Used at peak ".round(xdebug_peak_memory_usage()/1024,5)."Kb of Memory\n";
@@ -1,16 +0,0 @@
-class TestController implements RestController {
- public function execute(RestServer $rest) {
- $r .= '<p>URI: '.$rest->getRequest()->getRequestURI().'</p>';
- $r .= '<p>Method: '.$rest->getRequest()->getMethod().'</p>';
- $r .= '<p>User: '.$rest->getRequest()->getUser().'</p>';
- $r .= '<p>Password: '.$rest->getRequest()->getPassword().'</p>';
- $r .= '<p>$_GET["key"]: '.$rest->getRequest()->getGET('key').'</p>';
- $r .= '<p>$_POST["key"]: '.$rest->getRequest()->getPOST('key').'</p>';
- $r .= '<p>Body: '.$rest->getRequest()->getBody().'</p>';
- $rest->getResponse()->setResponse($r);
- return $rest;
-}
@@ -1,60 +0,0 @@
-include '../../RestClient.class.php';
-$base = "http://".$_SERVER["HTTP_HOST"].dirname($_SERVER["SCRIPT_NAME"]);
-var_dump($base);
-echo "\n<hr>\n";
-// The GET signature is get(URL,PARAMETERS,USER,PASSWORD), only the URI is mandatory;
-$get = RestClient::get($base."/rest.php",array("q"=>"diogok.json","key"=>"value"),"diogok","123");
-var_dump('$get = RestClient::get($base."/rest.php",array("q"=>"diogok.json","key"=>"value"),"diogok","123");');
-echo '<br>';
-var_dump($get->getResponseCode());
-echo $get->getResponse();
-// The POST signature is post(URL,PARAMETERS,USER,PASSWORD,CONTENT-TYPE) , only the URI is mandatory
-$get = RestClient::post($base."/rest.php",array("q"=>"diogok.json","key"=>"value"),"diogok","123");
-var_dump('$get = RestClient::post($base."/rest.php",array("q"=>"diogok.json","key"=>"value"),"diogok","123");');
-var_dump($get->getResponseCOde());
-$get = RestClient::post($base."/rest.php","This is my json","diogok","123","text/plain");
-var_dump('$get = RestClient::post($base."/rest.php","This is my json","diogok","123","text/plain");');
-$get = RestClient::post($base."/rest.php?key=diogok","This is my json","diogok","123","text/plain");
-var_dump('$get = RestClient::post($base."/rest.php?key=diogok","This is my json","diogok","123","text/plain");');
-// The PUT signature is put(URL,CONTENT,USER,PASSWORD,CONTENT-TYPE), the URL and CONTENT is mandatory
-$get = RestClient::put($base."/rest.php","This is my json","diogok","123","text/plain");
-var_dump('$get = RestClient::put($base."/rest.php","This is my json","diogok","123","text/plain");');
-// The DELETE signature is delete(URL,PARAMETERS,USER,PASSWORD), the URL is mandatory
-$get = RestClient::delete($base."/rest.php?key=diogok",array("key"=>"value"),"diogok","123");
-var_dump('$get = RestClient::delete($base."/rest.php?key=diogok",array("key"=>"value"),"diogok","123");');
-// The custom call signature is call(URL,PARAMETERS,USER,PASSWORD,CONTENT-TYPE), only the URL is mandatory
-$get = RestClient::call("OPTIONS",$base."/rest.php?key=diogok",array("key"=>"values"),"diogok","123","text/plain");
-var_dump('$get = RestClient::call("OPTIONS",$base."/rest.php?key=diogok",array("key"=>"values"),"diogok","123","text/plain");');
-include '../../RestServer.class.php';
-include 'TestController.class.php';
-$rest = new RestServer($_GET['q']) ;
-$rest->addMap("GET",".*","TestController");
-$rest->addMap("POST",".*","TestController");
-$rest->addMap("PUT",".*","TestController");
-$rest->addMap("DELETE",".*","TestController");
-$rest->addMap("OPTIONS",".*","TestController");
-echo $rest->execute();
f3acd66
f3acd66
f3acd66
f3acd66
f3acd66
f3acd66
f3acd66
f3acd66
f3acd66
f3acd66
f3acd66
f3acd66
f3acd66
f3acd66