diff options
author | Thomas Tanghus <thomas@tanghus.net> | 2013-09-28 01:35:24 +0200 |
---|---|---|
committer | Thomas Tanghus <thomas@tanghus.net> | 2013-10-01 20:13:13 +0200 |
commit | 973bcccd7cc18867ea22c24f83421ed180b5022c (patch) | |
tree | dcb1dcf2832b9c73c65f73d050bc9228a4f8f33d /lib/private/appframework/http | |
parent | 36d1156cf8fbd340ecfcc9d9a06e69004acfe154 (diff) | |
download | nextcloud-server-973bcccd7cc18867ea22c24f83421ed180b5022c.tar.gz nextcloud-server-973bcccd7cc18867ea22c24f83421ed180b5022c.zip |
Implement PUT an PATCH support
Diffstat (limited to 'lib/private/appframework/http')
-rw-r--r-- | lib/private/appframework/http/request.php | 101 |
1 files changed, 73 insertions, 28 deletions
diff --git a/lib/private/appframework/http/request.php b/lib/private/appframework/http/request.php index 5a86066b48b..3426f0bf752 100644 --- a/lib/private/appframework/http/request.php +++ b/lib/private/appframework/http/request.php @@ -31,10 +31,12 @@ use OCP\IRequest; class Request implements \ArrayAccess, \Countable, IRequest { + protected $content; protected $items = array(); protected $allowedKeys = array( 'get', 'post', + 'patch', 'files', 'server', 'env', @@ -50,7 +52,7 @@ class Request implements \ArrayAccess, \Countable, IRequest { * @param array 'params' the parsed json array * @param array 'urlParams' the parameters which were matched from the URL * @param array 'get' the $_GET array - * @param array 'post' the $_POST array + * @param array|string 'post' the $_POST array or JSON string * @param array 'files' the $_FILES array * @param array 'server' the $_SERVER array * @param array 'env' the $_ENV array @@ -62,11 +64,19 @@ class Request implements \ArrayAccess, \Countable, IRequest { public function __construct(array $vars=array()) { foreach($this->allowedKeys as $name) { - $this->items[$name] = isset($vars[$name]) + $this->items[$name] = isset($vars[$name]) ? $vars[$name] : array(); } + // Only 'application/x-www-form-urlencoded' requests are automatically + // transformed by PHP, 'application/json' must be decoded manually. + if (isset($this->items['post']) + && strpos($this->getHeader('Content-Type'), 'application/json') !== false + && is_string($this->items['post'])) { + $this->items['post'] = json_decode($this->items['post'], true); + } + $this->items['parameters'] = array_merge( $this->items['params'], $this->items['get'], @@ -141,19 +151,21 @@ class Request implements \ArrayAccess, \Countable, IRequest { * $request->myvar; or $request->{'myvar'}; or $request->{$myvar} * Looks in the combined GET, POST and urlParams array. * - * if($request->method !== 'POST') { - * throw new Exception('This function can only be invoked using POST'); - * } + * If you access e.g. ->post but the current HTTP request method + * is GET a \LogicException will be thrown. * * @param string $name The key to look for. + * @throws \LogicException * @return mixed|null */ public function __get($name) { switch($name) { + case 'put': + case 'patch': case 'get': case 'post': if($this->method !== strtoupper($name)) { - throw new \BadMethodCallException(sprintf('%s cannot be accessed in a %s request.', $name, $this->method)); + throw new \LogicException(sprintf('%s cannot be accessed in a %s request.', $name, $this->method)); } case 'files': case 'server': @@ -162,9 +174,13 @@ class Request implements \ArrayAccess, \Countable, IRequest { case 'parameters': case 'params': case 'urlParams': - return isset($this->items[$name]) - ? $this->items[$name] - : null; + if(in_array($name, array('put', 'patch'))) { + return $this->getContent($name); + } else { + return isset($this->items[$name]) + ? $this->items[$name] + : null; + } break; case 'method': return $this->items['method']; @@ -283,28 +299,57 @@ class Request implements \ArrayAccess, \Countable, IRequest { /** * Returns the request body content. * - * @param Boolean $asResource If true, a resource will be returned + * If the HTTP request method is PUT a stream resource is returned, otherwise an + * array or a string depending on the Content-Type. For "normal" use an array + * will be returned. * - * @return string|resource The request body content or a resource to read the body stream. + * @return array|string|resource The request body content or a resource to read the body stream. * * @throws \LogicException */ - function getContent($asResource = false) { - return null; -// if (false === $this->content || (true === $asResource && null !== $this->content)) { -// throw new \LogicException('getContent() can only be called once when using the resource return type.'); -// } -// -// if (true === $asResource) { -// $this->content = false; -// -// return fopen('php://input', 'rb'); -// } -// -// if (null === $this->content) { -// $this->content = file_get_contents('php://input'); -// } -// -// return $this->content; + protected function getContent() { + if ($this->content === false && $this->method === 'PUT') { + throw new \LogicException('"put" can only be accessed once.'); + } + + if (defined('PHPUNIT_RUN') && PHPUNIT_RUN + && in_array('fakeinput', stream_get_wrappers())) { + $stream = 'fakeinput://data'; + } else { + $stream = 'php://input'; + } + + if ($this->method === 'PUT') { + $this->content = false; + return fopen($stream, 'rb'); + } + + if (is_null($this->content)) { + $this->content = file_get_contents($stream); + + if ($this->method === 'PATCH') { + /* + * Normal jquery ajax requests are sent as application/x-www-form-urlencoded + * and in $_GET and $_POST PHP transformes the data into an array. + * The first condition mimics this. + * The second condition allows for sending raw application/json data while + * still getting the result as an array. + * + */ + if (strpos($this->getHeader('Content-Type'), 'application/x-www-form-urlencoded') !== false) { + parse_str($this->content, $content); + if(is_array($content)) { + $this->content = $content; + } + } elseif (strpos($this->getHeader('Content-Type'), 'application/json') !== false) { + $content = json_decode($this->content, true); + if(is_array($content)) { + $this->content = $content; + } + } + } + } + + return $this->content; } } |