Skip to content

Commit

Permalink
Automatically handle PUT requests
Browse files Browse the repository at this point in the history
make the following "just work"

    curl -X PUT -d foo=bar http://...
  • Loading branch information
AD7six committed Jun 6, 2012
1 parent d1475b1 commit b509bdb
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 2 deletions.
9 changes: 8 additions & 1 deletion lib/Cake/Network/CakeRequest.php
Expand Up @@ -161,7 +161,14 @@ public function __construct($url = null, $parseEnvironment = true) {
* @return void
*/
protected function _processPost() {
$this->data = $_POST;
if ($_POST) {
$this->data = $_POST;
} elseif ($this->is('put')) {
$this->data = $this->_readInput();
if (env('CONTENT_TYPE') === 'application/x-www-form-urlencoded') {
parse_str($this->data, $this->data);
}
}
if (ini_get('magic_quotes_gpc') === '1') {
$this->data = stripslashes_deep($this->data);
}
Expand Down
103 changes: 102 additions & 1 deletion lib/Cake/Test/Case/Network/CakeRequestTest.php
Expand Up @@ -21,6 +21,34 @@
App::uses('Xml', 'Utility');
App::uses('CakeRequest', 'Network');

class TestCakeRequest extends CakeRequest {

public $input;

public function reConstruct($url = 'some/path', $parseEnvironment = true) {
$this->_base();
if (empty($url)) {
$url = $this->_url();
}
if ($url[0] == '/') {
$url = substr($url, 1);
}
$this->url = $url;

if ($parseEnvironment) {
$this->_processPost();
$this->_processGet();
$this->_processFiles();
}
$this->here = $this->base . '/' . $this->url;
}

protected function _readInput() {
return $this->input;
}

}

class CakeRequestTest extends CakeTestCase {

/**
Expand All @@ -41,7 +69,7 @@ public function setUp() {
}

/**
* tearDown-
* tearDown
*
* @return void
*/
Expand Down Expand Up @@ -204,6 +232,79 @@ public function testPostParsing() {
$this->assertEquals($_POST, $request->data);
}

/**
* test parsing PUT data into the object.
*
* @return void
*/
public function testPutParsing() {
$_SERVER['REQUEST_METHOD'] = 'PUT';
$_SERVER['CONTENT_TYPE'] = 'application/x-www-form-urlencoded';

$data = array('data' => array(
'Article' => array('title')
));

$request = $this->getMock('TestCakeRequest', array('_readInput'));
$request->expects($this->at(0))->method('_readInput')
->will($this->returnValue('data[Article][]=title'));
$request->reConstruct();
$this->assertEquals($data['data'], $request->data);

$data = array('one' => 1, 'two' => 'three');
$request = $this->getMock('TestCakeRequest', array('_readInput'));
$request->expects($this->at(0))->method('_readInput')
->will($this->returnValue('one=1&two=three'));
$request->reConstruct();
$this->assertEquals($data, $request->data);

$data = array(
'data' => array(
'Article' => array('title' => 'Testing'),
),
'action' => 'update'
);
$request = $this->getMock('TestCakeRequest', array('_readInput'));
$request->expects($this->at(0))->method('_readInput')
->will($this->returnValue('data[Article][title]=Testing&action=update'));
$request->reConstruct();
$expected = array(
'Article' => array('title' => 'Testing'),
'action' => 'update'
);
$this->assertEquals($expected, $request->data);

$data = array('data' => array(
'Article' => array('title'),
'Tag' => array('Tag' => array(1, 2))
));
$request = $this->getMock('TestCakeRequest', array('_readInput'));
$request->expects($this->at(0))->method('_readInput')
->will($this->returnValue('data[Article][]=title&Tag[Tag][]=1&Tag[Tag][]=2'));
$request->reConstruct();
$this->assertEquals($data['data'], $request->data);

$data = array('data' => array(
'Article' => array('title' => 'some title'),
'Tag' => array('Tag' => array(1, 2))
));
$request = $this->getMock('TestCakeRequest', array('_readInput'));
$request->expects($this->at(0))->method('_readInput')
->will($this->returnValue('data[Article][title]=some%20title&Tag[Tag][]=1&Tag[Tag][]=2'));
$request->reConstruct();
$this->assertEquals($data['data'], $request->data);

$data = array(
'a' => array(1, 2),
'b' => array(1, 2)
);
$request = $this->getMock('TestCakeRequest', array('_readInput'));
$request->expects($this->at(0))->method('_readInput')
->will($this->returnValue('a[]=1&a[]=2&b[]=1&b[]=2'));
$request->reConstruct();
$this->assertEquals($data, $request->data);
}

/**
* test parsing of FILES array
*
Expand Down

5 comments on commit b509bdb

@markstory
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When merging and rebasing this code into my router/request branch for 3.0, I added support for PATCH and DELETE. Might make sense to add that to 2.2 as well. markstory/cakephp@e8680f6

@lorenzo
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 to add it to 2.2

@markstory
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added PUT/DELETE in 5467902 and updated the docs. :)

@AD7six
Copy link
Member Author

@AD7six AD7six commented on b509bdb Jun 18, 2012

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

win!

Why leave out patch though?

Are we going to get into semantic debates with users in the future as to why we aren't using PATCH for (partial) edit actions I wonder..

@markstory
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have patch in for 3.0, I guess we could add a is('patch') detector too. I hope we don't have that fight, its really not worth the time and effort.

Please sign in to comment.