Define interfaces more clearly and clean up code.
This commit is contained in:
parent
ac752bb446
commit
98e04ab63b
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
namespace pjdietz\WellRESTed\Exceptions;
|
namespace pjdietz\WellRESTed\Exceptions;
|
||||||
|
|
||||||
use \Exception;
|
use Exception;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Top level class for custom exceptions thrown by Well RESTed.
|
* Top level class for custom exceptions thrown by Well RESTed.
|
||||||
|
|
|
||||||
|
|
@ -10,33 +10,26 @@
|
||||||
|
|
||||||
namespace pjdietz\WellRESTed;
|
namespace pjdietz\WellRESTed;
|
||||||
|
|
||||||
|
use pjdietz\WellRESTed\Interfaces\HandlerInterface;
|
||||||
|
use pjdietz\WellRESTed\Interfaces\RequestInterface;
|
||||||
|
use pjdietz\WellRESTed\Interfaces\ResponseInterface;
|
||||||
|
use pjdietz\WellRESTed\Interfaces\RouterInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Handler issues a response for a given resource.
|
* A Handler issues a response for a given resource.
|
||||||
*
|
*
|
||||||
* @property-read Response response The Response to the request
|
* @property-read ResponseInterface response The Response to the request
|
||||||
*/
|
*/
|
||||||
abstract class Handler implements HandlerInterface
|
abstract class Handler implements HandlerInterface
|
||||||
{
|
{
|
||||||
/**
|
/** @var array Matches array from the preg_match() call used to find this Handler */
|
||||||
* Matches array from the preg_match() call used to find this Handler.
|
|
||||||
*
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
protected $args;
|
protected $args;
|
||||||
|
/** @var RequestInterface The HTTP request to respond to. */
|
||||||
/**
|
|
||||||
* The HTTP request to respond to.
|
|
||||||
*
|
|
||||||
* @var Request
|
|
||||||
*/
|
|
||||||
protected $request;
|
protected $request;
|
||||||
|
/** @var ResponseInterface The HTTP response to send based on the request. */
|
||||||
/**
|
|
||||||
* The HTTP response to send based on the request.
|
|
||||||
*
|
|
||||||
* @var Response
|
|
||||||
*/
|
|
||||||
protected $response;
|
protected $response;
|
||||||
|
/** @var RouterInterface The router that dispatched this handler */
|
||||||
|
protected $router;
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
// Accessors
|
// Accessors
|
||||||
|
|
@ -56,43 +49,43 @@ abstract class Handler implements HandlerInterface
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** @param array $args */
|
||||||
* @param array $args
|
|
||||||
*/
|
|
||||||
public function setArguments(array $args)
|
public function setArguments(array $args)
|
||||||
{
|
{
|
||||||
$this->args = $args;
|
$this->args = $args;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** @return array */
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function getArguments()
|
public function getArguments()
|
||||||
{
|
{
|
||||||
return $this->args;
|
return $this->args;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** @return RequestInterface */
|
||||||
* @param RequestInterface $request
|
|
||||||
*/
|
|
||||||
public function setRequest(RequestInterface $request)
|
|
||||||
{
|
|
||||||
$this->request = $request;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return \pjdietz\WellRESTed\Request
|
|
||||||
*/
|
|
||||||
public function getRequest()
|
public function getRequest()
|
||||||
{
|
{
|
||||||
return $this->request;
|
return $this->request;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** @param RequestInterface $request */
|
||||||
* Return the instance's Reponse
|
public function setRequest(RequestInterface $request)
|
||||||
*
|
{
|
||||||
* @return ResponseInterface
|
$this->request = $request;
|
||||||
*/
|
}
|
||||||
|
|
||||||
|
/** @return RouterInterface */
|
||||||
|
public function getRouter()
|
||||||
|
{
|
||||||
|
return $this->router;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @param RouterInterface $router */
|
||||||
|
public function setRouter(RouterInterface $router)
|
||||||
|
{
|
||||||
|
$this->router = $router;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return ResponseInterface */
|
||||||
public function getResponse()
|
public function getResponse()
|
||||||
{
|
{
|
||||||
$this->response = new Response();
|
$this->response = new Response();
|
||||||
|
|
@ -107,7 +100,7 @@ abstract class Handler implements HandlerInterface
|
||||||
*/
|
*/
|
||||||
protected function buildResponse()
|
protected function buildResponse()
|
||||||
{
|
{
|
||||||
switch ($this->request->method) {
|
switch ($this->request->getMethod()) {
|
||||||
|
|
||||||
case 'GET':
|
case 'GET':
|
||||||
$this->get();
|
$this->get();
|
||||||
|
|
@ -159,6 +152,14 @@ abstract class Handler implements HandlerInterface
|
||||||
$this->respondWithMethodNotAllowed();
|
$this->respondWithMethodNotAllowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide a default response for unsupported methods.
|
||||||
|
*/
|
||||||
|
protected function respondWithMethodNotAllowed()
|
||||||
|
{
|
||||||
|
$this->response->setStatusCode(405);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method for handling HTTP HEAD requests.
|
* Method for handling HTTP HEAD requests.
|
||||||
*
|
*
|
||||||
|
|
@ -171,8 +172,8 @@ abstract class Handler implements HandlerInterface
|
||||||
|
|
||||||
$this->get();
|
$this->get();
|
||||||
|
|
||||||
if ($this->response->statusCode == 200) {
|
if ($this->response->getStatusCode() == 200) {
|
||||||
$this->response->setBody('', false);
|
$this->response->setBody('');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -226,12 +227,4 @@ abstract class Handler implements HandlerInterface
|
||||||
$this->respondWithMethodNotAllowed();
|
$this->respondWithMethodNotAllowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Provide a default response for unsupported methods.
|
|
||||||
*/
|
|
||||||
protected function respondWithMethodNotAllowed()
|
|
||||||
{
|
|
||||||
$this->response->statusCode = 405;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace pjdietz\WellRESTed;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface for a creating a response in reaction to a respond or arguments.
|
|
||||||
* @package pjdietz\WellRESTed
|
|
||||||
*/
|
|
||||||
interface HandlerInterface
|
|
||||||
{
|
|
||||||
public function getRequest();
|
|
||||||
public function setRequest(RequestInterface $request);
|
|
||||||
public function getArguments();
|
|
||||||
public function setArguments(array $args);
|
|
||||||
public function getResponse();
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pjdietz\WellRESTed\Interfaces\HandlerInterface
|
||||||
|
*
|
||||||
|
* @author PJ Dietz <pj@pjdietz.com>
|
||||||
|
* @copyright Copyright 2013 by PJ Dietz
|
||||||
|
* @license MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace pjdietz\WellRESTed\Interfaces;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for a creating a response in reaction to a request or arguments.
|
||||||
|
* @package pjdietz\WellRESTed
|
||||||
|
*/
|
||||||
|
interface HandlerInterface
|
||||||
|
{
|
||||||
|
/** @return array Associative array used to obtain a response */
|
||||||
|
public function getArguments();
|
||||||
|
|
||||||
|
/** @param array $args Associative array used to obtain a response */
|
||||||
|
public function setArguments(array $args);
|
||||||
|
|
||||||
|
/** @return RequestInterface Request used to obtain a response */
|
||||||
|
public function getRequest();
|
||||||
|
|
||||||
|
/** @param RequestInterface $request Request used to obtain a response */
|
||||||
|
public function setRequest(RequestInterface $request);
|
||||||
|
|
||||||
|
/** @return RouterInterface Reference to the router used to dispatch this handler */
|
||||||
|
public function getRouter();
|
||||||
|
|
||||||
|
/** @param RouterInterface $router Request used to obtain a response */
|
||||||
|
public function setRouter(RouterInterface $router);
|
||||||
|
|
||||||
|
/** @return ResponseInterface Response obtained based on the args and request */
|
||||||
|
public function getResponse();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pjdietz\WellRESTed\Interfaces\RequestInterface
|
||||||
|
*
|
||||||
|
* @author PJ Dietz <pj@pjdietz.com>
|
||||||
|
* @copyright Copyright 2013 by PJ Dietz
|
||||||
|
* @license MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace pjdietz\WellRESTed\Interfaces;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for representing an HTTP request.
|
||||||
|
* @package pjdietz\WellRESTed
|
||||||
|
*/
|
||||||
|
interface RequestInterface
|
||||||
|
{
|
||||||
|
/** @return string HTTP request method (e.g., GET, POST, PUT). */
|
||||||
|
public function getMethod();
|
||||||
|
|
||||||
|
/** @return string Path component of the request URI */
|
||||||
|
public function getPath();
|
||||||
|
|
||||||
|
/** @return array Query paramters as key-value pairs */
|
||||||
|
public function getQuery();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the value for this header name
|
||||||
|
*
|
||||||
|
* @param $headerName
|
||||||
|
* @return string $headerName
|
||||||
|
*/
|
||||||
|
public function getHeader($headerName);
|
||||||
|
|
||||||
|
/** @return string Requst body */
|
||||||
|
public function getBody();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pjdietz\WellRESTed\Interfaces\ResponseInterface
|
||||||
|
*
|
||||||
|
* @author PJ Dietz <pj@pjdietz.com>
|
||||||
|
* @copyright Copyright 2013 by PJ Dietz
|
||||||
|
* @license MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace pjdietz\WellRESTed\Interfaces;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for representing an HTTP response.
|
||||||
|
* @package pjdietz\WellRESTed
|
||||||
|
*/
|
||||||
|
interface ResponseInterface
|
||||||
|
{
|
||||||
|
/** @return int HTTP status code */
|
||||||
|
public function getStatusCode();
|
||||||
|
|
||||||
|
/** @param int $statusCode HTTP status code */
|
||||||
|
public function setStatusCode($statusCode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the value for this header name
|
||||||
|
*
|
||||||
|
* @param $headerName
|
||||||
|
* @return string $headerName
|
||||||
|
*/
|
||||||
|
public function getHeader($headerName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $headerName
|
||||||
|
* @param string $headerValue
|
||||||
|
*/
|
||||||
|
public function setHeader($headerName, $headerValue);
|
||||||
|
|
||||||
|
/** @return string */
|
||||||
|
public function getBody();
|
||||||
|
|
||||||
|
/** @param string $body */
|
||||||
|
public function setBody($body);
|
||||||
|
|
||||||
|
/** Issue the reponse to the client. */
|
||||||
|
public function respond();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pjdietz\WellRESTed\Interfaces\RouteInterface
|
||||||
|
*
|
||||||
|
* @author PJ Dietz <pj@pjdietz.com>
|
||||||
|
* @copyright Copyright 2013 by PJ Dietz
|
||||||
|
* @license MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace pjdietz\WellRESTed\Interfaces;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for a route to relate a pattern for matching a URI to a handler class.
|
||||||
|
* @package pjdietz\WellRESTed
|
||||||
|
*/
|
||||||
|
interface RouteInterface
|
||||||
|
{
|
||||||
|
/** @return string Regex pattern used to match the URI */
|
||||||
|
public function getPattern();
|
||||||
|
|
||||||
|
/** @para string $pattern Regex pattern used to match the URI */
|
||||||
|
public function setPattern($pattern);
|
||||||
|
|
||||||
|
/** @return string Fully qualified name of the class the route will dispatch. */
|
||||||
|
public function getHandler();
|
||||||
|
|
||||||
|
/** @param string $className Fully qualified name of the class the route will dispatch. */
|
||||||
|
public function setHandler($className);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pjdietz\WellRESTed\Interfaces\RouterInterface
|
||||||
|
*
|
||||||
|
* @author PJ Dietz <pj@pjdietz.com>
|
||||||
|
* @copyright Copyright 2013 by PJ Dietz
|
||||||
|
* @license MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace pjdietz\WellRESTed\Interfaces;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The RouterInterface provides a mechanism for obtaining a response given a request.
|
||||||
|
* @package pjdietz\WellRESTed
|
||||||
|
*/
|
||||||
|
interface RouterInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Return the response for the given request.
|
||||||
|
*
|
||||||
|
* @param RequestInterface $request
|
||||||
|
* @return ResponseInterface
|
||||||
|
*/
|
||||||
|
public function getResponse(RequestInterface $request = null);
|
||||||
|
}
|
||||||
|
|
@ -21,20 +21,10 @@ namespace pjdietz\WellRESTed;
|
||||||
*/
|
*/
|
||||||
abstract class Message
|
abstract class Message
|
||||||
{
|
{
|
||||||
/**
|
/** @var string Entity body of the message */
|
||||||
* Entity body of the message
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
protected $body;
|
protected $body;
|
||||||
|
/** @var array Associative array of HTTP headers */
|
||||||
/**
|
|
||||||
* Associative array of HTTP headers
|
|
||||||
*
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
protected $headers;
|
protected $headers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Associative array of lowercase header field names as keys with
|
* Associative array of lowercase header field names as keys with
|
||||||
* corresponding case sensitive field names from the $headers array as
|
* corresponding case sensitive field names from the $headers array as
|
||||||
|
|
@ -43,19 +33,9 @@ abstract class Message
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $headerLookup;
|
protected $headerLookup;
|
||||||
|
/** @var string Name of the protocol to use. */
|
||||||
/**
|
|
||||||
* Name of the protocol to use.
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
protected $protocol = 'HTTP';
|
protected $protocol = 'HTTP';
|
||||||
|
/** @var string Version of the protocol to use. */
|
||||||
/**
|
|
||||||
* Version of the protocol to use.
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
protected $protocolVersion = '1.1';
|
protected $protocolVersion = '1.1';
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
|
|
@ -156,9 +136,7 @@ abstract class Message
|
||||||
return isset($this->body);
|
return isset($this->body);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Unset the body property */
|
||||||
* Unset the body property
|
|
||||||
*/
|
|
||||||
public function unsetBody()
|
public function unsetBody()
|
||||||
{
|
{
|
||||||
unset($this->body);
|
unset($this->body);
|
||||||
|
|
@ -315,9 +293,7 @@ abstract class Message
|
||||||
return isset($this->protocol);
|
return isset($this->protocol);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Unset the protocol property. */
|
||||||
* Unset the protocol property.
|
|
||||||
*/
|
|
||||||
public function unsetProtocol()
|
public function unsetProtocol()
|
||||||
{
|
{
|
||||||
unset($this->protocol);
|
unset($this->protocol);
|
||||||
|
|
@ -353,9 +329,7 @@ abstract class Message
|
||||||
return isset($this->protocolVersion);
|
return isset($this->protocolVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Unset the version portion of the protocol. */
|
||||||
* Unset the version portion of the protocol.
|
|
||||||
*/
|
|
||||||
public function unsetProtocolVersion()
|
public function unsetProtocolVersion()
|
||||||
{
|
{
|
||||||
unset($this->protocolVersion);
|
unset($this->protocolVersion);
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
namespace pjdietz\WellRESTed;
|
namespace pjdietz\WellRESTed;
|
||||||
|
|
||||||
// TODO: Include port in the URI
|
use pjdietz\WellRESTed\Interfaces\RequestInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Request instance represents an HTTP request. This class has two main uses:
|
* A Request instance represents an HTTP request. This class has two main uses:
|
||||||
|
|
@ -31,40 +31,7 @@ namespace pjdietz\WellRESTed;
|
||||||
*/
|
*/
|
||||||
class Request extends Message implements RequestInterface
|
class Request extends Message implements RequestInterface
|
||||||
{
|
{
|
||||||
/**
|
// TODO: Include port in the URI
|
||||||
* The Hostname for the request (e.g., www.google.com)
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $hostname;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* HTTP method or verb for the request
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $method = 'GET';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Path component of the URI for the request
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $path = '/';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Array of fragments of the path, delimited by slashes
|
|
||||||
*
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
private $pathParts;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Associative array of query parameters
|
|
||||||
*
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
private $query;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Singleton instance derived from reading info from Apache.
|
* Singleton instance derived from reading info from Apache.
|
||||||
|
|
@ -73,6 +40,16 @@ class Request extends Message implements RequestInterface
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
static protected $theRequest;
|
static protected $theRequest;
|
||||||
|
/** @var string The Hostname for the request (e.g., www.google.com) */
|
||||||
|
private $hostname;
|
||||||
|
/** @var string HTTP method or verb for the request */
|
||||||
|
private $method = 'GET';
|
||||||
|
/** @var string Path component of the URI for the request */
|
||||||
|
private $path = '/';
|
||||||
|
/** @var array Array of fragments of the path, delimited by slashes */
|
||||||
|
private $pathParts;
|
||||||
|
/**@var array Associative array of query parameters */
|
||||||
|
private $query;
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
@ -96,6 +73,62 @@ class Request extends Message implements RequestInterface
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
// Accessors
|
// Accessors
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the URI for the Request. This sets the other members, such as path,
|
||||||
|
* hostname, etc.
|
||||||
|
*
|
||||||
|
* @param string $uri
|
||||||
|
*/
|
||||||
|
public function setUri($uri)
|
||||||
|
{
|
||||||
|
$parsed = parse_url($uri);
|
||||||
|
|
||||||
|
$host = isset($parsed['host']) ? $parsed['host'] : '';
|
||||||
|
$this->setHostname($host);
|
||||||
|
|
||||||
|
$path = isset($parsed['path']) ? $parsed['path'] : '';
|
||||||
|
$this->setPath($path);
|
||||||
|
|
||||||
|
$query = isset($parsed['query']) ? $parsed['query'] : '';
|
||||||
|
$this->setQuery($query);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a reference to the singleton instance of the Request derived
|
||||||
|
* from the server's information about the request sent to the script.
|
||||||
|
*
|
||||||
|
* @return Request
|
||||||
|
* @static
|
||||||
|
*/
|
||||||
|
public static function getRequest()
|
||||||
|
{
|
||||||
|
if (!isset(self::$theRequest)) {
|
||||||
|
$request = new Request();
|
||||||
|
$request->readHttpRequest();
|
||||||
|
self::$theRequest = $request;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$theRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set instance members based on the HTTP request sent to the server.
|
||||||
|
*/
|
||||||
|
public function readHttpRequest()
|
||||||
|
{
|
||||||
|
$this->setBody(file_get_contents("php://input"), false);
|
||||||
|
$this->headers = apache_request_headers();
|
||||||
|
|
||||||
|
// Add case insensitive headers to the lookup table.
|
||||||
|
foreach ($this->headers as $key => $value) {
|
||||||
|
$this->headerLookup[strtolower($key)] = $key;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->method = $_SERVER['REQUEST_METHOD'];
|
||||||
|
$this->uri = $_SERVER['REQUEST_URI'];
|
||||||
|
$this->hostname = $_SERVER['HTTP_HOST'];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the hostname portion of the URI
|
* Return the hostname portion of the URI
|
||||||
*
|
*
|
||||||
|
|
@ -195,6 +228,8 @@ class Request extends Message implements RequestInterface
|
||||||
return $this->query;
|
return $this->query;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the query. The value passed can be a query string of key-value pairs
|
* Set the query. The value passed can be a query string of key-value pairs
|
||||||
* joined by ampersands or it can be an associative array.
|
* joined by ampersands or it can be an associative array.
|
||||||
|
|
@ -232,28 +267,6 @@ class Request extends Message implements RequestInterface
|
||||||
return $uri;
|
return $uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the URI for the Request. This sets the other members, such as path,
|
|
||||||
* hostname, etc.
|
|
||||||
*
|
|
||||||
* @param string $uri
|
|
||||||
*/
|
|
||||||
public function setUri($uri)
|
|
||||||
{
|
|
||||||
$parsed = parse_url($uri);
|
|
||||||
|
|
||||||
$host = isset($parsed['host']) ? $parsed['host'] : '';
|
|
||||||
$this->setHostname($host);
|
|
||||||
|
|
||||||
$path = isset($parsed['path']) ? $parsed['path'] : '';
|
|
||||||
$this->setPath($path);
|
|
||||||
|
|
||||||
$query = isset($parsed['query']) ? $parsed['query'] : '';
|
|
||||||
$this->setQuery($query);
|
|
||||||
}
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make a cURL request out of the instance and return a Response.
|
* Make a cURL request out of the instance and return a Response.
|
||||||
*
|
*
|
||||||
|
|
@ -335,40 +348,4 @@ class Request extends Message implements RequestInterface
|
||||||
return $resp;
|
return $resp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Set instance members based on the HTTP request sent to the server.
|
|
||||||
*/
|
|
||||||
public function readHttpRequest()
|
|
||||||
{
|
|
||||||
$this->setBody(file_get_contents("php://input"), false);
|
|
||||||
$this->headers = apache_request_headers();
|
|
||||||
|
|
||||||
// Add case insensitive headers to the lookup table.
|
|
||||||
foreach ($this->headers as $key => $value) {
|
|
||||||
$this->headerLookup[strtolower($key)] = $key;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->method = $_SERVER['REQUEST_METHOD'];
|
|
||||||
$this->uri = $_SERVER['REQUEST_URI'];
|
|
||||||
$this->hostname = $_SERVER['HTTP_HOST'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a reference to the singleton instance of the Request derived
|
|
||||||
* from the server's information about the request sent to the script.
|
|
||||||
*
|
|
||||||
* @return Request
|
|
||||||
* @static
|
|
||||||
*/
|
|
||||||
public static function getRequest()
|
|
||||||
{
|
|
||||||
if (!isset(self::$theRequest)) {
|
|
||||||
$request = new Request();
|
|
||||||
$request->readHttpRequest();
|
|
||||||
self::$theRequest = $request;
|
|
||||||
}
|
|
||||||
|
|
||||||
return self::$theRequest;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace pjdietz\WellRESTed;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface for representing an HTTP request.
|
|
||||||
* @package pjdietz\WellRESTed
|
|
||||||
*/
|
|
||||||
interface RequestInterface
|
|
||||||
{
|
|
||||||
public function getMethod();
|
|
||||||
public function setMethod($method);
|
|
||||||
public function getUri();
|
|
||||||
public function setUri($uri);
|
|
||||||
}
|
|
||||||
|
|
@ -10,7 +10,8 @@
|
||||||
|
|
||||||
namespace pjdietz\WellRESTed;
|
namespace pjdietz\WellRESTed;
|
||||||
|
|
||||||
use \InvalidArgumentException;
|
use InvalidArgumentException;
|
||||||
|
use pjdietz\WellRESTed\Interfaces\ResponseInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Response instance allows you to build an HTTP response and send it when
|
* A Response instance allows you to build an HTTP response and send it when
|
||||||
|
|
@ -31,12 +32,7 @@ class Response extends Message implements ResponseInterface
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
private $reasonPhrase;
|
private $reasonPhrase;
|
||||||
|
/** @var int HTTP status code */
|
||||||
/**
|
|
||||||
* HTTP status code
|
|
||||||
*
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
private $statusCode;
|
private $statusCode;
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
|
|
@ -84,26 +80,12 @@ class Response extends Message implements ResponseInterface
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** @return string Portion of the status line explaining the status. */
|
||||||
* Return the portion of the status line explaining the status.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getReasonPhrase()
|
public function getReasonPhrase()
|
||||||
{
|
{
|
||||||
return $this->reasonPhrase;
|
return $this->reasonPhrase;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true if the status code is in the 2xx range.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function getSuccess()
|
|
||||||
{
|
|
||||||
return $this->statusCode >= 200 && $this->statusCode < 300;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assign an explaination for the status code. Not normally needed.
|
* Assign an explaination for the status code. Not normally needed.
|
||||||
*
|
*
|
||||||
|
|
@ -114,11 +96,13 @@ class Response extends Message implements ResponseInterface
|
||||||
$this->reasonPhrase = $statusCodeMessage;
|
$this->reasonPhrase = $statusCodeMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** @return bool True if the status code is in the 2xx range. */
|
||||||
* Return the status code.
|
public function getSuccess()
|
||||||
*
|
{
|
||||||
* @return int
|
return $this->statusCode >= 200 && $this->statusCode < 300;
|
||||||
*/
|
}
|
||||||
|
|
||||||
|
/** @return int */
|
||||||
public function getStatusCode()
|
public function getStatusCode()
|
||||||
{
|
{
|
||||||
return $this->statusCode;
|
return $this->statusCode;
|
||||||
|
|
@ -268,24 +252,6 @@ class Response extends Message implements ResponseInterface
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return HTTP status line, e.g. HTTP/1.1 200 OK.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
protected function getStatusLine()
|
|
||||||
{
|
|
||||||
return sprintf(
|
|
||||||
'%s/%s %s %s',
|
|
||||||
strtoupper($this->protocol),
|
|
||||||
$this->protocolVersion,
|
|
||||||
$this->statusCode,
|
|
||||||
$this->reasonPhrase
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Output the response to the client.
|
* Output the response to the client.
|
||||||
*
|
*
|
||||||
|
|
@ -307,4 +273,18 @@ class Response extends Message implements ResponseInterface
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/** @return string HTTP status line, e.g. HTTP/1.1 200 OK. */
|
||||||
|
protected function getStatusLine()
|
||||||
|
{
|
||||||
|
return sprintf(
|
||||||
|
'%s/%s %s %s',
|
||||||
|
strtoupper($this->protocol),
|
||||||
|
$this->protocolVersion,
|
||||||
|
$this->statusCode,
|
||||||
|
$this->reasonPhrase
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace pjdietz\WellRESTed;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface for representing an HTTP response.
|
|
||||||
* @package pjdietz\WellRESTed
|
|
||||||
*/
|
|
||||||
interface ResponseInterface
|
|
||||||
{
|
|
||||||
public function respond();
|
|
||||||
}
|
|
||||||
|
|
@ -10,7 +10,8 @@
|
||||||
|
|
||||||
namespace pjdietz\WellRESTed;
|
namespace pjdietz\WellRESTed;
|
||||||
|
|
||||||
use \Exception;
|
use pjdietz\WellRESTed\Exceptions\WellRESTedException;
|
||||||
|
use pjdietz\WellRESTed\Interfaces\RouteInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Route connects a URI pattern to a Handler.
|
* A Route connects a URI pattern to a Handler.
|
||||||
|
|
@ -22,33 +23,26 @@ class Route implements RouteInterface
|
||||||
* digits, hyphen and underscore)
|
* digits, hyphen and underscore)
|
||||||
*/
|
*/
|
||||||
const RE_SLUG = '[0-9a-zA-Z\-_]+';
|
const RE_SLUG = '[0-9a-zA-Z\-_]+';
|
||||||
|
|
||||||
/** Regular expression matching digitis */
|
/** Regular expression matching digitis */
|
||||||
const RE_NUM = '[0-9]+';
|
const RE_NUM = '[0-9]+';
|
||||||
|
|
||||||
/** Regular expression matching letters */
|
/** Regular expression matching letters */
|
||||||
const RE_ALPHA = '[a-zA-Z]+';
|
const RE_ALPHA = '[a-zA-Z]+';
|
||||||
|
|
||||||
/** Regular expression matching letters and digits */
|
/** Regular expression matching letters and digits */
|
||||||
const RE_ALPHANUM = '[0-9a-zA-Z]+';
|
const RE_ALPHANUM = '[0-9a-zA-Z]+';
|
||||||
|
|
||||||
/** Regular expression matching a URI template variable (e.g., {id}) */
|
/** Regular expression matching a URI template variable (e.g., {id}) */
|
||||||
const URI_TEMPLATE_EXPRESSION_RE = '/{([a-zA-Z]+)}/';
|
const URI_TEMPLATE_EXPRESSION_RE = '/{([a-zA-Z]+)}/';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default regular expression used to match template variable
|
* Default regular expression used to match template variable
|
||||||
*
|
*
|
||||||
* @property string
|
* @property string
|
||||||
*/
|
*/
|
||||||
static public $defaultVariablePattern = self::RE_SLUG;
|
static public $defaultVariablePattern = self::RE_SLUG;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Regular expression used to match a Request URI path component
|
* Regular expression used to match a Request URI path component
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
private $pattern;
|
private $pattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Name of the Handler class to use
|
* Name of the Handler class to use
|
||||||
*
|
*
|
||||||
|
|
@ -68,45 +62,13 @@ class Route implements RouteInterface
|
||||||
$this->handler = $handler;
|
$this->handler = $handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $handler
|
|
||||||
*/
|
|
||||||
public function setHandler($handler)
|
|
||||||
{
|
|
||||||
$this->handler = $handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getHandler()
|
|
||||||
{
|
|
||||||
return $this->handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $pattern
|
|
||||||
*/
|
|
||||||
public function setPattern($pattern)
|
|
||||||
{
|
|
||||||
$this->pattern = $pattern;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getPattern()
|
|
||||||
{
|
|
||||||
return $this->pattern;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new Route using a URI template to generate the pattern.
|
* Create a new Route using a URI template to generate the pattern.
|
||||||
*
|
*
|
||||||
* @param string $uriTemplate
|
* @param string $uriTemplate
|
||||||
* @param string $handler
|
* @param string $handler
|
||||||
* @param array $variables
|
* @param array $variables
|
||||||
* @throws Exception
|
* @throws WellRESTedException
|
||||||
* @return Route
|
* @return Route
|
||||||
*/
|
*/
|
||||||
static public function newFromUriTemplate(
|
static public function newFromUriTemplate(
|
||||||
|
|
@ -155,7 +117,7 @@ class Route implements RouteInterface
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Not sure why this would happen.
|
// Not sure why this would happen.
|
||||||
throw new Exception('Invalid URI Template.');
|
throw new WellRESTedException('Invalid URI Template.');
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -173,4 +135,36 @@ class Route implements RouteInterface
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getHandler()
|
||||||
|
{
|
||||||
|
return $this->handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $handler
|
||||||
|
*/
|
||||||
|
public function setHandler($handler)
|
||||||
|
{
|
||||||
|
$this->handler = $handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getPattern()
|
||||||
|
{
|
||||||
|
return $this->pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $pattern
|
||||||
|
*/
|
||||||
|
public function setPattern($pattern)
|
||||||
|
{
|
||||||
|
$this->pattern = $pattern;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace pjdietz\WellRESTed;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface for a route to relate a pattern for matching a URI to a handler class.
|
|
||||||
* @package pjdietz\WellRESTed
|
|
||||||
*/
|
|
||||||
interface RouteInterface
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Return the regex pattern used to match the URI
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getPattern();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provide a regex pattern that matches the URI
|
|
||||||
*
|
|
||||||
* @para string $pattern
|
|
||||||
*/
|
|
||||||
public function setPattern($pattern);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the name of the class the route will dispatch.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getHandler();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provide the classname to instantiate to handle the route.
|
|
||||||
*
|
|
||||||
* @param string $className
|
|
||||||
*/
|
|
||||||
public function setHandler($className);
|
|
||||||
}
|
|
||||||
|
|
@ -10,24 +10,25 @@
|
||||||
|
|
||||||
namespace pjdietz\WellRESTed;
|
namespace pjdietz\WellRESTed;
|
||||||
|
|
||||||
|
use pjdietz\WellRESTed\Interfaces\HandlerInterface;
|
||||||
|
use pjdietz\WellRESTed\Interfaces\RequestInterface;
|
||||||
|
use pjdietz\WellRESTed\Interfaces\ResponseInterface;
|
||||||
|
use pjdietz\WellRESTed\Interfaces\RouteInterface;
|
||||||
|
use pjdietz\WellRESTed\Interfaces\RouterInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Router
|
* Router
|
||||||
*
|
*
|
||||||
* A Router uses a table of Routes to find the appropriate Handler for a
|
* A Router uses a table of Routes to find the appropriate Handler for a request.
|
||||||
* request.
|
|
||||||
*/
|
*/
|
||||||
class Router
|
class Router implements RouterInterface
|
||||||
{
|
{
|
||||||
/**
|
/** @var string Fully qualified name for the interface for handlers */
|
||||||
* Array of Route objects
|
const HANDLER_INTERFACE = '\\pjdietz\\WellRESTed\\Interfaces\\HandlerInterface';
|
||||||
*
|
/** @var array Array of Route objects */
|
||||||
* @var array
|
private $routes;
|
||||||
*/
|
|
||||||
protected $routes;
|
|
||||||
|
|
||||||
/**
|
/** Create a new Router. */
|
||||||
* Create a new Router.
|
|
||||||
*/
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->routes = array();
|
$this->routes = array();
|
||||||
|
|
@ -44,28 +45,29 @@ class Router
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the Response built by the Handler based on the Request
|
* Return the response built by the handler based on the request
|
||||||
*
|
*
|
||||||
* @param Request $request
|
* @param RequestInterface $request
|
||||||
* @return Response
|
* @return ResponseInterface
|
||||||
*/
|
*/
|
||||||
public function getResponse($request = null)
|
public function getResponse(RequestInterface $request = null)
|
||||||
{
|
{
|
||||||
if (is_null($request)) {
|
if (is_null($request)) {
|
||||||
$request = Request::getRequest();
|
$request = Request::getRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
$path = $request->path;
|
$path = $request->getPath();
|
||||||
|
|
||||||
foreach ($this->routes as $route) {
|
foreach ($this->routes as $route) {
|
||||||
/** @var RouteInterface $route */
|
/** @var RouteInterface $route */
|
||||||
if (preg_match($route->getPattern(), $path, $matches)) {
|
if (preg_match($route->getPattern(), $path, $matches)) {
|
||||||
$handlerClassName = $route->getHandler();
|
$handlerClassName = $route->getHandler();
|
||||||
if (is_subclass_of($handlerClassName, '\pjdietz\WellRESTed\HandlerInterface')) {
|
if (is_subclass_of($handlerClassName, self::HANDLER_INTERFACE)) {
|
||||||
/** @var HandlerInterface $handler */
|
/** @var HandlerInterface $handler */
|
||||||
$handler = new $handlerClassName();
|
$handler = new $handlerClassName();
|
||||||
$handler->setRequest($request);
|
$handler->setRequest($request);
|
||||||
$handler->setArguments($matches);
|
$handler->setArguments($matches);
|
||||||
|
$handler->setRouter($this);
|
||||||
return $handler->getResponse();
|
return $handler->getResponse();
|
||||||
} else {
|
} else {
|
||||||
return $this->getNoRouteResponse($request);
|
return $this->getNoRouteResponse($request);
|
||||||
|
|
@ -77,15 +79,15 @@ class Router
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare a Resonse indicating a 404 Not Found error
|
* Prepare a resonse indicating a 404 Not Found error
|
||||||
*
|
*
|
||||||
* @param Request $request
|
* @param RequestInterface $request
|
||||||
* @return Response
|
* @return ResponseInterface
|
||||||
*/
|
*/
|
||||||
protected function getNoRouteResponse(Request $request)
|
protected function getNoRouteResponse(RequestInterface $request)
|
||||||
{
|
{
|
||||||
$response = new Response(404);
|
$response = new Response(404);
|
||||||
$response->body = 'No resource at ' . $request->uri;
|
$response->body = 'No resource at ' . $request->getPath();
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue