» CakePHP REST Plugin presentation

At our company we have a lot of uses for a solid API. We can use it to distribute config files, have servers report in, let customers edit DNS records using their own interface, etc.

Now that I'm converting all of our legacy code to a big CakePHP application, the API needed a revisit as well. I chose to use REST as a standard, read about everything related to Cake & REST, and started hacking on a reusable plugin. The idea is that you can drop it in any application and unlock existing functionality to REST with minimal changes to your code.

It is still a work in progress, but as the first Dutch CakePHP event was held yesterday and I was asked to present something I thought this particular plugin might be of interest to the community. Here are the slides:

View on slideshare

And here's the source & documentation on github

I would love some feedback to help it make better. My todos can be found in the slides as well, to give you an idea where I'm heading with this.

More info on the Dutch CakePHP event

You probably shouldn't follow me


Like this Article?

I'd appreciate it if you leave a comment, spread the word, or consider a small donation


tags: cakephp, programming, rest, php, api
category: Programming - PHP - CakePHP
read: 17,356 times

Add comment

(required, shown)(required, not shown)for syntax highlighting

[CODE="Javascript"]
your_code_here();
[/CODE]

Replace "Javascript"
with "php", "text", etc.
code (to make sure you are not a spammer)

 Track replies: rss feed comments feed

Comments

#44. Kevin on 15 December 2011

Twitter.com: kvz@ Gary: There is a 2.0 branch that works just fine for us

#43. Gary on 09 December 2011

Gravatar.com: GaryWhat would it take to get this to work with CakePHP 2.0?

#42. Chris on 23 November 2011

Gravatar.com: ChrisI figured my problem out after reading deeper into the comments. I was not defining which controller actions I wanted to expose.

'actions'=>array(
'index'=>array(
'extract'=>array('prospects')
)
)


That will make it work on function index() and json/xml encode the $prospects array.

#41. Chris on 23 November 2011

Gravatar.com: ChrisHi, just trying to get this working. I thought I had everything but I get the following error: The requested address '/prospects/links.json' was not found on this server.

My controller code is

public $components = array(
'RequestHandler',
'Rest.Rest' => array(
'catchredir' => true, // Recommended unless you implement something yourself
'debug' => 0,
'view' => array(
'extract' => array('server.Server' => 'servers.0'),
),
'index' => array(
'extract' => array('rows.{n}.Server' => 'servers'),
),
),
);
 
function links(){
$this->autoRender = false;
$this->autoLayout = false;
//var_dump($this->Rest->credentials());
//var_dump($this->Rest->isActive()); die();
Configure::write('debug',0);
$conditions = array('conditions'=>array('user_id'=>1));
$arr = $this->Prospect->find('all',$conditions);
$this->set('json',$arr);
$this->set(compact('json'));
}


My htaccess looks like:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule ^$ app/webroot/ [L]
RewriteRule (.*) app/webroot/$1 [L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]

# Adds AUTH support to Rest Plugin:
RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization},last]
</IfModule>

And my routes.php is

Router::mapResources(array('Prospects'));
 
// Add XML + JSON to your parseExtensions
Router::parseExtensions('json','xml');

#40. chiacy on 14 November 2011

Gravatar.com: chiacyBack again with problem on Authentication.

I tried the authentication, first, I do not know how apikey is generated, but that's not really a matter.

What matters me is that once a client logged in with correct KEYWORD, username and password, and when trying to access subsequently the same site from the same client, as long as KEYWORD is correct, even without username and password, I can still access to the data.
... [more]
I wonder if this is due to cookies, but I have disabled cookie from my cakephp component to eliminate the possibility, no good result.

Anyone out the can help pointing out I have done wrong?

added the following to component settings:

'onlyActiveWithAuth'=>true,
'catchredir' => false,

both either true or false, no effect.


before filter function of the controller

if (!$this->Auth->user()) {
// Try to login user via REST
if ($this->Rest->isActive()) {
$credentials=$this->Rest->credentials();
$this->Auth->autoRedirect = false;
$data = array(
$this->Auth->userModel => array(
'username' => $credentials['username'],
'password' => $credentials['password'],
),
);
$data = $this->Auth->hashPasswords($data);
if (!$this->Auth->login($data)) {
$msg = sprintf('Unable to log you in with the supplied credentials. ');
return $this->Rest->abort(array('status' => '403', 'error' => $msg));
}
}
}


Thanks

#39. chiacy on 14 November 2011

Gravatar.com: chiacyI got it!

changes made here:

'actions'=>array(
... [more] 'index' => array(
'extract' => array('users'),
),
),

instead of just


'index' => array(
'extract' => array('users'),
),


Thank you!!!

#38. linkingarts on 14 November 2011

Gravatar.com: linkingartsAm having same problem as chiacy and others - no data.

I have updated my controller to use actions => array but this only gives me {"data":{"mythings":[null]}...}

Any help most appreciated. Great plugin, thank you for opening it up (I have used it before on other sites - not sure why is not working now!).

#37. chiacy on 13 November 2011

Gravatar.com: chiacyHi Kevin,

This is THE plugin I am dreaming of! It allows me to systematically convert existing cake app to REST based.

To test, I am using one of my cake app and play around with User Controller.
... [more]
I have follow every step you mentioned in your read me etc, and read thru all comments, but I can't seems to get the right.

Currently, no authentication is implemented, just to make it as simple as possible until I get the desired result.

Below is the problem
My data is always empty, as shown below

{"data":[],"meta":{"status":"ok","feedback":[],"request":{"http_host":"127.0.0.1","http_user_agent":"Rested 2.0.1 (Macintosh; Mac OS X 10.7.2; en_MY)","server_addr":"127.0.0.1","remote_addr":"127.0.0.1","server_protocol":"HTTP/1.1","request_method":"GET","request_uri":"/ap5/users/index.json","request_time":1321202674},"credentials":{"class":null,"apikey":null,"username":null},"time_epoch":"1321202674","time_local":"Mon, 14 Nov 2011 00:44:34 +0800","version":"0.3"}}

Appreciate if you can point me to the solution.

component settings as below:

'Rest.Rest'=>array(
'catchredir' => false, // Recommended unless you implement something yourself
//'debug' => 2,
'view' => array(
'extract' => array('user'),
),
'index' => array(
'extract' => array('users'),
),
'ratelimit'=>false,
'log'=>null,
'extensions' => array('xml', 'json', 'csv'),
),

Users Controller index function

function index() {
$this->User->recursive = 0;
$users=$this->User->find('all');
//$this->set('users', $this->paginate());
$this->set(compact('users'));
debug($users);
}

thank you in advance

#36. albert liga on 09 November 2011

Gravatar.com: albert ligahi, i don't understand how to implement REST in cake 1.3.x.x

can you help me how to create REST plugin in cake step by step???

#35. Scott McDonnell on 23 August 2011

Gravatar.com: Scott McDonnellGreat plugin! 2 issues I found with the current documentation when I was testing:

1. In Authorization the example does not set $credentials

// Try to login user via REST
if ($this->Rest->isActive()) {
$credentials = $this->Rest->credentials();
...


2. The 2 examples in Usage are not in the new format ie. contained in an 'action' array. They should read
'Rest.Rest' => array(
'catchredir' => true, // Recommended unless you implement something yourself
'debug' => 0,
'actions' => array(
'view' => array(
'extract' => array('server.Server' => 'servers.0'),
),
'index' => array(
'extract' => array('rows.{n}.Server' => 'servers'),
),
),
),
...


and
'Rest.Rest' => array(
'catchredir' => true,
'actions'=> array(
'extract' => array(
'index' => array('tweets'),
),
),
),
...

Just makes it a lot easier to get going quickly!

#34. Peter DeMartini on 23 August 2011

Gravatar.com: Peter DeMartiniThis plugin is great! however I am super confused on how to authenticate. I read the amazon S3 authentication docs and I am still confused. Can you or someone post example of how to get a JSON response with authentication. I tried to follow the directions in the documentation but I remain bewildered. I am new to REST and JSON so more information would be much appreciated.

#33. Carlos on 08 June 2011

Gravatar.com: CarlosHi Kevin, forgive my ignorance: what does your plugin do that the built-in Cakephp REST does not provide?

http://book.cakephp.org/view/1238/REST

As far as I can tell:
... [more] - authentication
- json support
- rate limiting
- logging

Did I miss anything?

#32. Diego Massanti on 27 April 2011

Gravatar.com: Diego MassantiHello Kevin, thanks for this nice piece of code, i've been using this for the past hours for a service that im working on and it is great.
But like some other people asked here, i would like to see an example of how to deal with checking if rest is enabled inside my error handler.

Right now i have a custom subclass of errorHandler for my custom errors, and unless i send a reference to the calling controller to my custom error function, i can not figure out how to get a reference to the Rest plugin, could you post some actual code example on how you dealt with this ?

... [more] Thanks.
Diego.

#31. Kevin on 17 April 2011

Twitter.com: kvz@ Freddy & Juan: Are you sure you are nesting the data correctly? e.g. inside proper model names? What about dumping $_POST? Does that give you any clues?

@ Florus: That's not really enough information to go on, sorry.

#30. Florus on 12 April 2011

Gravatar.com: FlorusHey Kevin,

With CakePHP 1.3.8. running (fresh install) I tried to get your Rest plugin into action. But I'm getting errors when I try to access .json or .xml via browser.
I have the mapResources set and the parseExtensions etc, like your install notes says.
The parsing via the browser seems to handle the content-type well, like for xml and json, but the content itself are errors only..
... [more]
Thanks, Florus

#29. Freddy on 05 April 2011

Gravatar.com: FreddyI found, just comment the line $this->headers(); at the end of the initialize function.
This line are not important because the problem the function headers() want to fixe isn't a problem. The header are good when your debug level is 0 (both REST and Core).

#28. Freddy on 04 April 2011

Gravatar.com: FreddyI've got the same problem than @Juan.
When I use the REST component, for ADD action $this->data is empty (it works fine when i don't use this component).
ps : sorry for my english, i'm french

#27. Juan on 28 March 2011

Gravatar.com: JuanI'm trying to get the plugin to work using an add function (all GET requests work great) but when I send some data to be POSTed $this->data is empty. I'm trying to do it via AJAX w/ JQuery. I've tried xml and json but maybe I just don't know how. Could you help me out?

#26. Kevin on 04 March 2011

Twitter.com: kvz@ Carlos: What I meant was, inside your normal error handler, do a check for rest and then e.g. output: json_encode(array('error' => $errmsg))

#25. Gary on 27 February 2011

Gravatar.com: GaryYes, it's working for me now that you've disabled the Auth by default.

Thanks!

#24. Kevin on 23 February 2011

Twitter.com: kvz@ luqash, Marco, Cazza, Gary: I've been investigating a bit. Could it be that you're not setting an Auth keyword in your client request headers? The component is now configured to let Cake handle it. So normal Cake would throw view not found.

This behavior is configurable but I changed the default:
https://github.com/kvz/cakephp-rest-plugin/commit/c05c59b506054e1e06113b2562414607e962e344

... [more] Let me know if that helps!

#23. luqash on 22 February 2011

Gravatar.com: luqashsame issue here as Marco, Cazza and Gary

using CakePHP 1.3.7

#22. Marco on 04 February 2011

Gravatar.com: MarcoReally nice work Kevin!
But I have same problem Cazza and Gary have, do we miss something?
Do you guys got this problem and managed to resolve?

Thanks in advance.

#21. Carlos on 31 January 2011

Gravatar.com: Carlos"A check if REST is active inside your error handler"

Can you provide a code sample for this? Slide #14 touches on this but I can't figure out to code it.

My problem is that code errors (not api call errors) get output in XML/JSON so debugging is messy.
... [more]
Ideally code errors would cause rest output to deactivate and output the errors in regular HTML (instead of invalid xml/json).

Thanks!

#20. Babar on 31 December 2010

Gravatar.com: BabarHi Kevin,
i am getting this Fatal error: Class 'XmlView' not found in D:xampphtdocsltfcakelibscontrollercontroller.php on line 775, and i am unable to debug it.

#19. Gary on 31 December 2010

Gravatar.com: GaryHi Kevin,

This will significant simplify my development, if I can get it to work.

Unfortunately, I'm getting the same results as Cazze. Whenver I try to access a .json or .xml, I get a "Missing View" error saying I need to create xml/index.ctp and json/index.ctp files.
... [more]
I'm using Cake 1.3.6. Is there an incompatibility with this version?

#18. Francisco on 10 December 2010

Gravatar.com: FranciscoI need to implement 2-legged oauth in my api with cakephp, if someone can help me.

#17. Cazze on 06 December 2010

Gravatar.com: CazzeHi,

i tried your plugin, but when i go to .xml or .json, i always got an error view not found.
Do i have to create views for xml and json?

#16. Kevin on 31 October 2010

Twitter.com: kvz@ Chris: Thanks, I've updated the readme file accordingly!

#15. Chris on 27 October 2010

Gravatar.com: ChrisHi Kevin,

Great plugin!

Just wanted to say I was only able to get it working after creating the rest_logs table (using the sql in config/schema/rest_logs.sql) - if I didn't do that, I got a Page not found error message when attempting to get the .json version.
... [more]
Might be helpful for anyone else experiencing the same issue.

Chris

#14. Kevin on 14 October 2010

Twitter.com: kvz@ Paul Winkeler: Happy to announce my plugin now supports Cake 1.3!

#13. Kevin on 08 September 2010

Twitter.com: kvz@ Paul Winkeler: Haven't tested it yet, in fact it's one of the last todos.
But if you feel like giving it a spin.. I'd be happy to learn your findings / accept your patches.

#12. Paul Winkeler on 16 August 2010

Gravatar.com: Paul WinkelerThis REST plugin for cakephp is exactly what the Dr ordered. Does it indeed work for cakephp version 1.3 as well?

#11. Kevin on 29 June 2010

Twitter.com: kvz@ steve: Look like it's your webserver: http://www.checkupdown.com/status/E413.html

Furthermore, you may find the clien-side of this API interesting that I developed for my company:
http://github.com/true/true-api

#10. steve on 22 June 2010

Gravatar.com: steveHi... I figured out how to implement 2-legged OAuth with my API, but I now have another issue that I can't figure out. Have you ever executed a HTTP PUT with files? I keep getting 413 errors when send when I try to PUT anything to my API. Here are what the headers look like, any advice?:

[0] => Content-Disposition: attachment; filename="DSC01264.JPG"
[1] => Content-Type: application/octet-stream
[2] => Content-Length: 64250
... [more] [3] => Authorization: OAuth realm="", oauth_requester_id="720", oauth_signature_method="HMAC-SHA1", oauth_signature="Rom3hREK8p2PzMBXdzIJb3hy%2FF0%3D", oauth_nonce="4c210a01d83d9", oauth_timestamp="1277233665", oauth_token="", oauth_consumer_key="1385adb7be6ade0a0bf7d5493fd0722404c1795eb", oauth_version="1.0", xoauth_body_signature="8ap46NO3buRxIbzAtFc5OFa6FNY%3D"

thanks,

Steve

#9. steve on 11 June 2010

Gravatar.com: steveKevin thanks for the reply! Do you have any hints on how I could handle this Amazon Authentication... Do you happen to have an expample I could see?
I am building a REST API now, and I could use all the advice I could get.
Thanks!
Steve

#8. Kevin on 10 June 2010

Twitter.com: kvz@ steve: Hey, no your app still handles the authentication, that's what makes it flexible. But it parses the string for you and inside your login procedure you just check for it with

$this->Rest->credentials();


as (kind of) explained on: http://github.com/kvz/cakephp-rest-plugin

#7. steve on 08 June 2010

Gravatar.com: steveKevin,
Thank you very much for this plugin! I am a bit confused about the authentication. Does this plugin actually handle the Amazon-style authentication and return the appropriate HTTP response codes? Or, does it simply parse out the Amazon-style Header:

`Authorization: TRUEREST username=john&password=xxx&apikey=247b5a2f72df375279573f2746686daa`

... [more] into an array that can then be used effectively with some other security component?

Thanks,

Steve

#6. Kevin on 29 April 2010

Twitter.com: kvz@ gkibria: Did you make the necessary parseExtensions adjustments in your router so that Cake will try to parse json?

Your index is fine.
If in that controller you specify:

public $components = array(
'Rest.Rest' => array(
'debug' => 1,
'index' => array(
'extract' => array('products' => 'myProducts'),
),
),
);


It should show you the contents of products under 'myProducts' in json format, when you browse to /index.json

#5. gkibria on 24 April 2010

Gravatar.com: gkibriaThanks for info. But when I enable Rest.Rest component in products controller, I can't browse neither /products/index nor /products/index.json and after disable the component it works fine. any idea?

And Here is my index()

function index() {
$this->Product->recursive = 0;
$this->set('products', $this->paginate());

}


my cake_core is 1.25 thanks

#4. Kevin on 24 April 2010

Twitter.com: kvz@ gkibria: Only .json is supported for now. You should try that.
No the trick is you

$this->set('name', 'gkibria');

like you would normally with your index()

Only the restcomponent can take the viewVars you specify, maybe even convert them into another (more rest-consistent) format, and them json_encode them.
XML serialization is being worked on.

#3. gkibria on 24 April 2010

Gravatar.com: gkibriaHello

Thanks for your plugin. I have a products controller with index action working fine. When I added Rest.Rest component in my products controller I got "Error: The requested address '/products' was not found on this server." for /products

And /products.xml give me" XML Parsing Error: no element found"
... [more]
When I disable Rest.Rest component, /products are working fine. Can you tell me what's wrong?

Another thing, Do I have to place any additional code in index() action?

Many Thanks

#2. Kevin on 14 March 2010

Twitter.com: kvz@ Tamas Jozsa: Hey. No you tie it in with existing controllers & actions. So if you already have:
/posts/view/1

you could add the Rest component to your PostsController and then you could do
/posts/view/1.json
... [more]
to get the same data but in json format and with additional features like authentication

#1. Tamas Jozsa on 12 March 2010

Gravatar.com: Tamas JozsaHi Kevin,

This plug-in is exactly what I'm searching for. Will try it out today and when I have time I will return to give a feedback.

One thing I do not understand so far is, how to call this from a browser. Is it like:
... [more]
www.hostname.com/rest/<modelname>s ???

And how to select whether to output to JSON or XML. As I see in the code XML is there in many places.

Thanks,
Regards,
Tamas