cakefest 2010: api development
DESCRIPTION
TRANSCRIPT
API Development
Becoming the Platform(CakePHP for Back-End Developmentor Cake for Web Services)By Andrew Curioso
CakeFest2010
Introduction
Yesterday: Designing CakePHP plug-ins for
consuming APIs Today:
Create your own API▪ Basic setup▪ Extras
Become a platform
Be “a” platform A blog is a platform
Become a platform
Internal only (closed) Multi-platform
(consumers) Scalable
External (open) Everything + Growth▪ Mash-ups!▪ Innovation▪ Evangelists
“The Platform Play”
Who’s already a platform Google Facebook Digg Twitter Yahoo BOSS /
Flickr / Delicious / etc.
Salesforce Ebay Amazon
Gowalla FourSquare Bit.ly Paypal Authorize.net Etc…
Types of APIs
PATTERNS
Representation State Transfer (REST)
Remote Procedure Calls (RPC)
PROTOCOLS / FORMATS XML JSON YAML AMF Etc...
RESTful
Representational State Transfer Resource based (nouns) 5 verbs
GET PUT POST DELETE HEAD
Easy in CakePHP
Today’s App
URL shortening website User authentication (simple) Create, read, update, and delete (CRUD)
Models
id user_id url created modified
users urls
Making it RESTful
APP/config/routes.php Router::mapResource(‘users’)
Verb URL Controller Method
GET /users.json UsersController::index()
GET /user/123.json UsersController::view(123)
POST /users.json UsersController::add()
PUT /users/123.json UsersController::edit(123)
DELETE /users/123.json UsersController::delete(123)
POST /users/123.json UsersController::edit(123)
Source: http://book.cakephp.org/view/1239/The-Simple-Setup
Security Pitfall
Only you can prevent CSRF Only POST and PUT should write data Only POST and DELETE should delete
data
Mapping Extensions
Router::parseExtensions() RequestHandler component
Switches layouts / views Includes helpers Parses incoming XML on POST
Router::connect( "/:controller/:id”, array ("action" => "edit", "[method]" => "PUT"), array("id" => "[0-9]+”));
Source: http://book.cakephp.org/view/1240/Custom-REST-Routing
Json View
Simple Fast Wide-spread
<?php echo json_encode( $url );?>
APP/views/urls/json/view.ctp
JsonP
P w/ padding Uses callback Cross domain
<?php if ( $callbackFunc !==
false ) echo $callbackFunc.'(';
echo $content_for_layout;
if ( $callbackFunc ) echo $callbackFunc.')'; ?>
APP/views/layouts/json/default.ctp
function beforeFilter(){
if ( array_key_exists('callback’, $this->params[‘url’]) ) $this->set(‘callbackFunc’, $this->params[‘url’]
[‘callback’]);
else $this->set(‘callbackFunc’, false);
}
APP/app_controller.php
XML View
Strongly Typed Human readable Lots of existing tools
<? echo ‘<url>’; echo $xml->serialize( $url ); echo ‘<url>’;?>
APP/views/urls/xml/view.ctp
Other Views
HUMAN READABLE
XML Json / JsonP HTML YAML CSV Serialized PHP Etc…
BINARY
AMF Microsoft Excel PDF JPEG / PNG Etc…
Testing It Out Using cURL
curl –d “url=www.example.com” http://tinyr.me/urls.json
Create
curl http://tinyr.me/urls/123.json
Read
curl –d “url=www.example.com/foo” http://tinyr.me/urls/123.json
Update
curl –X DELETE http://tinyr.me/urls/123.json
Delete
Done?
WE HAVE
MVC files RESTful Views
XML Json / JsonP
WE’RE MISSING
Error handling Pagination Authentication Authorization Documentation
Status Codes
Success 200 OK * 201 Created * 303 See Other *
Error 401 Unauthorized * 402 Payment
Required 403 Forbidden * 404 Not Found *
Error (continued) 405 Method Not
Allowed * 409 Conflict 410 Gone 500 Internal Server
Error 501 Not Implemented 503 Service
Unavailable
Add Method
If not a POST request 405 Method Not Allowed
Already existed 303 See Other
Save success 201 Created
Failure 200 OK with explanation
Edit Method
If not a POST or PUT request 405 Method Not Allowed
Invalid ID 404 File Not Found
Success 200 OK
Failure 200 OK with explanation
Delete Method
If not a POST or DELETE request 405 Method Not Allowed
Invalid ID 404 File Not Found
Success 200 OK
Failure 200 OK with explanation
Global
User is not allowed to access resource 403 Forbidden
User is not logged in 401 Unauthorized
Throwing Errors
Same format Descriptive
Human Computer
Comprehensive
Implementation
function your_action() { … $this->_userError(404); …}
function _userError( $code, $options=array() ) { $codes = array( 402 => 'Payment Required', … ); $this->header("HTTP/1.1 {$type} {$codes[$type]}"); $this->cakeError('error'.$type, array( array( 'options' => $options ) ) );}
APP/app_controller.php
APP/controllers/your_controller.php
Implementation
{"Error": { "code" : 404, "description" : "File Not Found"}}
APP/views/errors/error404.ctp
HTTP Headers
Return meta-information Rate limiting Pagination Etc.
Pagination
Uses HTTP headers App defined start with “X-”
function paginate($object=NULL, $scope=array(), $whitelist=array() ) { $data = parent::paginate($object,$scope,$whitelist);
// … messy code to get the object …
$this->header('X-Current-Page: '.((int)$this->params['paging'][$object->alias]['page'])); $this->header('X-Page-Limit: '.((int)$this->params['paging'][$object->alias]['options']
['limit'])); $this->header('X-Page-Total: '.((int)$this->params['paging'][$object->alias]['count']));
return $data;}
APP/app_controller.php
Multi-Platform Dev
Use a UI that makes sense Bring something to the table
Platform Support
WEB BROWSERS
Do not support: DELETE PUT
FORTUNATELY CAKE…
Let’s you do this:
_method=DELETE
Platform Support
DELETE /urls/123.json HTTP1.1Host: www.example.com
POST /urls/123.json HTTP1.1Host: www.example.com
_method=DELETE
Authentication
Authorization
There is no magic One or more:
user_id Administrator Moderator
Documentation
Vocabularies / Schemas DTD or schema files
Examples Code I/O
Community Feedback
What about SOAP and AMF?
CakePHP rocks with REST SOAP is heavy AMF is light but requires Flash But, if you still want to, you can
Flow for SOAP and AMF
Example Flow
Router AmfController UrlsController
::gateway()
::view()
Return data
Format envelope
User
POST
Some final words…
Don’t Choose
Views are easy
API Developers Checklist
Documentation Example code
Definition files (if applicable) Unit tests
Finding the code
MIT License http://tinyr.me
Happy Aniversary
Happy anniversary, Laura. 1 year: Sept. 5, 2010
Andrew Curioso
Contact: www.AndrewCurioso.com/contact @AndrewCurioso on Twitter