Top Banner
Create a RESTful api Sept 1, 2012 CakeFest 2012 CakeFest 2012 Manchester
60
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Cake fest 2012 create a restful api

Create a RESTful apiSept 1, 2012

CakeFest 2012

CakeFest 2012 Manchester

Page 2: Cake fest 2012 create a restful api

INTRODUCTION

CakeFest 2012 Manchester

Marc Ypes@Ceeram

CakePHP 4 yearsCore team 1.5 years

Undercover as programmer

Page 3: Cake fest 2012 create a restful api

OVERVIEW

CakeFest 2012 Manchester

REST my case?REST your Cake

■ Content-type■ Routing■ Interface■ Authentication■ Cache■ Errors

Page 4: Cake fest 2012 create a restful api

INTRODUCTION TO REST

CakeFest 2012 Manchester

Representational state transfer

Set of architectural principles

- resource focussed- manipulation through representations- HTTP protocol?

Page 5: Cake fest 2012 create a restful api

INTRODUCTION TO REST

CakeFest 2012 Manchester

Constraints

■ Client-server■ Stateless■ Uniform interface■ Cacheable■ Layered system

Page 6: Cake fest 2012 create a restful api

INTRODUCTION TO REST

CakeFest 2012 Manchester

Uniform interface

■ resource

■ identification of the resource

■ manipulation through representation

■ self-descriptive

■ hypermedia as the engine of application state HATEOAS

Page 7: Cake fest 2012 create a restful api

INTRODUCTION TO REST

CakeFest 2012 Manchester

Uniform Interface

Data element Exampleresource user, book etc. (users, books etc.)resource identifier URL, URN (/users/1234)representation

data TXT / HTML / XML /YAML,JSONmetadata content type, last-modified time

resource metadata source link, alternatecontrol data if-modified-since, cache-control, etag

http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm

Page 8: Cake fest 2012 create a restful api

INTRODUCTION TO REST

CakeFest 2012 Manchester

Uniform Interface

/api/getUserProfile/1234/api/addVoteForUser?id=1234/api/users?action=vote&id=1234/api/deleteUser/1/api/deleteUser?id=1/api/favoritedUsers/api/getUserData/1?fields=name,email

Page 9: Cake fest 2012 create a restful api

INTRODUCTION TO REST

CakeFest 2012 Manchester

Uniform Interface

GET /users Get collectionPOST /users Add to collectionGET /users/1234 Get resourcePUT /users/1234 Update resourceDELETE /users/1234 Delete resource

Update is not update?POST /users/1234

Page 10: Cake fest 2012 create a restful api

INTRODUCTION TO REST

CakeFest 2012 Manchester

Uniform Interface

Typical request:

>GET /books/1849511926 HTTP/1.1>Host: api.amazin.com>Accept: application/json

>If-Modified-Since: Sat, 01 Sep 2012 10:22:36 GMT

Page 11: Cake fest 2012 create a restful api

INTRODUCTION TO REST

CakeFest 2012 Manchester

Uniform Interface

Typical response:

< HTTP/1.1 200 OK< Date: Sat, 01 Sep 2012 11:45:12 GMT< Server: Apache/2.2.16 (Debian)< Last-Modified: Sat, 01 Sep 2012 11:25:31 GMT< Content-Length: 145< Content-Type: application/json{"book":{........"}}

Page 12: Cake fest 2012 create a restful api

INTRODUCTION TO REST

CakeFest 2012 Manchester

Uniform Interface

Typical response:

< HTTP/1.1 304 Not Modified< Date: Sat, 01 Sep 2012 11:45:12 GMT< Server: Apache/2.2.16 (Debian)< Vary: Accept-Encoding

Page 13: Cake fest 2012 create a restful api

INTRODUCTION TO REST

CakeFest 2012 Manchester

Uniform Interface

Safe methodsIdempotent methods

GET (HEAD) is safe (nullipotent)PUT, DELETE are idempotent

POSTPATCH?

Page 14: Cake fest 2012 create a restful api

INTRODUCTION TO REST

CakeFest 2012 Manchester

Uniform Interface

Normalize the resources

GET /books/1849511926/votes

GET /votes?book=1849511926

Page 15: Cake fest 2012 create a restful api

INTRODUCTION TO REST

CakeFest 2012 Manchester

Uniform Interface

Normalize the resources

POST /books/1849511926/votes

PUT /books/1849511926data contains votes subresource data

POST /votesdata is book=1849511926

Page 16: Cake fest 2012 create a restful api

INTRODUCTION TO REST

CakeFest 2012 Manchester

Uniform Interface

PATCH

Edge Rails: PATCH is the new primary HTTP method for updates

http://weblog.rubyonrails.org/2012/2/25/edge-rails-patch-is-the-new-primary-http-method-for-updates/

Page 17: Cake fest 2012 create a restful api

INTRODUCTION TO REST

CakeFest 2012 Manchester

Uniform Interface / HATEOAS

Level 3 of REST maturity model (RMM)

Page 18: Cake fest 2012 create a restful api

INTRODUCTION TO REST

CakeFest 2012 Manchester

Uniform Interface / HATEOAS

Level 0

Single URI, single HTTP method

Page 19: Cake fest 2012 create a restful api

INTRODUCTION TO REST

CakeFest 2012 Manchester

Uniform Interface / HATEOAS

Level 1

Many URI, single HTTP method

Page 20: Cake fest 2012 create a restful api

INTRODUCTION TO REST

CakeFest 2012 Manchester

Uniform Interface / HATEOAS

Level 2

Many URI, different HTTP methods

Page 21: Cake fest 2012 create a restful api

INTRODUCTION TO REST

CakeFest 2012 Manchester

Uniform Interface / HATEOAS

Level 2

Many URI, different HTTP methods

Page 22: Cake fest 2012 create a restful api

INTRODUCTION TO REST

CakeFest 2012 Manchester

Uniform Interface / HATEOAS

Level 3

Self descriptive■ Media types■ Links■ Other protocols

Page 23: Cake fest 2012 create a restful api

INTRODUCTION TO REST

CakeFest 2012 Manchester

Uniform Interface / HATEOAS

HATEOAS

GET /comments?book=1849511926

Link to api.amazin.com/books/1849511926

Links to all comments

Page 24: Cake fest 2012 create a restful api

INTRODUCTION TO REST

CakeFest 2012 Manchester

Uniform Interface / HATEOAS

>GET /comments/1<HTTP/1.1 200 Ok<Content-Type: text/xml<?xml version="1.0"><comment>

<foo>great book</foo><book>

<link href="/books/1849511926" title="wow" /></book>

</vote>

Page 25: Cake fest 2012 create a restful api

INTRODUCTION TO REST

CakeFest 2012 Manchester

Uniform Interface / HATEOAS{

"foo":"bar","book":

{"links":[

{"href":"/book/1849511926", "title":"wow"

}]

}}

Page 26: Cake fest 2012 create a restful api

INTRODUCTION TO REST

CakeFest 2012 Manchester

Uniform Interface / HATEOAS

Link header

Link: <https://api.github.com/user/repos?page=2&per_page=100>;rel="next", <https://api.github.com/user/repos?page=50&per_page=100>;rel="last"

github.com

Page 27: Cake fest 2012 create a restful api

INTRODUCTION TO REST

CakeFest 2012 Manchester

Uniform Interface / Errors

HTTP Statuscodes

Human reads messageCode reads code

Page 28: Cake fest 2012 create a restful api

INTRODUCTION TO REST

CakeFest 2012 Manchester

Uniform Interface / Errors

HTTP Statuscodes

200 OK201 Created204 No Content304 Not Modified400 Bad Request401 Unauthorized404 Not Found405 Method Not Allowed

Page 29: Cake fest 2012 create a restful api

INTRODUCTION TO REST

CakeFest 2012 Manchester

Uniform Interface / Errors

Link to support page

Link: <http://api.amazin.com/errors/405>; rel="help"

Page 30: Cake fest 2012 create a restful api

INTRODUCTION TO REST

CakeFest 2012 Manchester

Cacheable

HTTP Cache headers

Use them!

Page 31: Cake fest 2012 create a restful api

INTRODUCTION TO REST

CakeFest 2012 Manchester

Cacheable

HTTP Cache headers

Cache-control- private- public- max-age / s-maxage- must-revalidate- nocache

Page 32: Cake fest 2012 create a restful api

INTRODUCTION TO REST

CakeFest 2012 Manchester

Cacheable

HTTP Cache validation

Etag RSLast-Modified RS

If-Modified-Since RQIf-None-Match RQ

If-Match RQ

Page 33: Cake fest 2012 create a restful api

INTRODUCTION TO REST

CakeFest 2012 Manchester

REST might not be what you are looking for

Questions?

Rest my Cake

Page 34: Cake fest 2012 create a restful api

REST my Cake

CakeFest 2012 Manchester

Basic setup

Route urls with extensions

http://localhost/cats/index.json

app/Config/routes.php<?php// allow any url extensionRouter::parseExtensions();

//or allow .json extension onlyRouter::parseExtensions('json');

Page 35: Cake fest 2012 create a restful api

REST my Cake

CakeFest 2012 Manchester

Basic setup

Add RequestHandler component<?phpApp::uses('Controller', 'Controller');

class AppController extends Controller {

public $components = array( 'DebugKit.Toolbar', 'Session', 'RequestHandler', );}

Page 36: Cake fest 2012 create a restful api

REST my Cake

CakeFest 2012 Manchester

Basic setup

Create view files, the CakePHP 1.3 way (almost)

app/View/Cats/json/index.ctp

<?php echo json_encode($cats) ;?>

Page 37: Cake fest 2012 create a restful api

REST my Cake

CakeFest 2012 Manchester

Basic setup

Use auto serialization, the CakePHP 2.x way

public function view($id = null) { $this->Cat->id = $id; if (!$this->Cat->exists()) { throw new NotFoundException(__('Invalid cat')); } $this->set('cat', $this->Cat->read(null, $id)); $this->set('_serialize', array('cat')); }

Page 38: Cake fest 2012 create a restful api

REST my Cake

CakeFest 2012 Manchester

http://localhost/cats/index.json

Page 39: Cake fest 2012 create a restful api

REST my Cake

CakeFest 2012 Manchester

http://localhost/cats/view/1.json

Page 40: Cake fest 2012 create a restful api

REST my Cake

CakeFest 2012 Manchester

REST Routing

Resource mapping

http://localhost/catshttp://localhost/cats/1

app/Config/routes.php

Router::mapResources(array('Cats', 'Users'));

Page 41: Cake fest 2012 create a restful api

REST my Cake

CakeFest 2012 Manchester

REST Routing

Resource mapping

GET /cats index()POST /cats add()GET /cats/1 view(1)POST /cats/1 edit(1)PUT /cats/1 edit(1)DELETE /cats/1 delete(1)

Page 42: Cake fest 2012 create a restful api

REST my Cake

CakeFest 2012 Manchester

REST Routing

Resource mapping

X-HTTP-Method-Override<Limit PUT DELETE> order deny,allow allow from all</Limit>

Page 43: Cake fest 2012 create a restful api

REST my Cake

CakeFest 2012 Manchester

REST Routing

Resource mappingapp/Config/routes.phpRouter::resourceMap(array( array('action' => 'index','method' => 'GET','id' => false), array('action' => 'read','method' => 'GET','id' => true), array('action' => 'add','method' => 'POST','id' => false), array('action' => 'edit','method' => 'POST','id' => true), array('action' => 'replace','method' => 'PUT','id' => true), array('action' => 'update','method' => 'PATCH','id' => true), array('action' => 'delete','method' => 'DELETE','id' => true)

array('action' => 'truncate','method'=>'DELETE','id'=>false)));

Page 44: Cake fest 2012 create a restful api

REST my Cake

CakeFest 2012 Manchester

REST Routing

Resource mappingapp/Config/routes.phpRouter::mapResources(

array('Cats', 'Users', 'Pizza.Orders'));

/cats => CatsController::index() in app/users => UsersController::index() in app/pizza/orders => OrdersController::index() in Pizza plugin

Page 45: Cake fest 2012 create a restful api

REST my Cake

CakeFest 2012 Manchester

REST Routing

Resource mappingapp/Config/routes.phpRouter::mapResources(

array('Cats', 'Users', 'Pizza.Orders'),array('prefix' => '/api/')

);

/api/cats => CatsController::index() in app/api/users => UsersController::index() in app/api/orders => OrdersController::index() in Pizza plugin

Page 46: Cake fest 2012 create a restful api

REST my Cake

CakeFest 2012 Manchester

REST Routing

Resource mappingapp/Config/routes.phpRouter::mapResources(

array('Cats', 'Users', 'Pizza.Orders'),array('prefix' => '/api/, 'id' => Router::UUID')

);

/api/cats => CatsController::index() in app/api/users => UsersController::index() in app/api/orders => OrdersController::index() in Pizza plugin

Page 47: Cake fest 2012 create a restful api

REST my Cake

CakeFest 2012 Manchester

REST Routing

.json?format=json

curl -H "Accept: application/json" http://localhost/cats

Page 48: Cake fest 2012 create a restful api

REST my Cake

CakeFest 2012 Manchester

REST Routing

GET /cats/sleepingGET /cats?status=sleepingGET /cats?sleeping=1

GET /posts/recentGET /posts?type=recent

Page 49: Cake fest 2012 create a restful api

REST my Cake

CakeFest 2012 Manchester

REST Routing

/posts/foo/bar routes with passed params/posts/foo:bar routes with named paramsapp/Config/routes.phpRouter::connect('/api/cats/*',

array( 'plugin' => null, 'controller' => 'posts', 'action' => 'index', '[method]' => 'GET'));

Page 50: Cake fest 2012 create a restful api

REST my Cake

CakeFest 2012 Manchester

REST Routing

GET /users/vote/1234POST /users/vote/1234 $this->Html->postLink()POST /api/users/1234/votespublic function vote($id = null) {

//user id exist, httpmethod checks etc.$this->User->updateAll(

array('User.votes' => 'User.votes + 1'),array('User.id' => $id)

);}

Page 51: Cake fest 2012 create a restful api

REST my Cake

CakeFest 2012 Manchester

REST Routing

POST /users/1234/votesapp/Config/routes.phpRouter::connect('/api/users/:id/votes',

array( 'plugin' => null, 'controller' => 'users', 'action' => 'vote', '[method]' => 'POST'

),array('id' => Router::ID, 'pass' => 'id')

);

Page 52: Cake fest 2012 create a restful api

REST my Cake

CakeFest 2012 Manchester

REST Routing

POST /users/1234/votespublic function vote($id = null) {

//user id exist checks etc$this->User->Vote->add($id);

}POST /votespublic function add() {

$this->Vote->add($this->request->data['Vote.user']);}

Page 53: Cake fest 2012 create a restful api

REST my Cake

CakeFest 2012 Manchester

REST Routing

CakeRequest::addDetector('patch',array(

'env' => 'REQUEST_METHOD','value' => 'PATCH'

));

Page 55: Cake fest 2012 create a restful api

REST my Cake

CakeFest 2012 Manchester

CakeResponse

cache( $since, $time = '+1 day' )checkNotModified( $request )disableCache( )etag( $tag = NULL, $weak = false )expires( $time = NULL )maxAge( $seconds = NULL )modified( $time = NULL )mustRevalidate( $enable = NULL )notModified( )sharable( $public = NULL, $time = NULL )sharedMaxAge( $seconds = NULL )

Page 56: Cake fest 2012 create a restful api

REST my Cake

CakeFest 2012 Manchester

RequestHandlerComponent

public $components = array('RequestHandler' => array(

'viewClassMap' => array('json' => 'RestJson','xml' => 'RestXml'

))

);

Page 57: Cake fest 2012 create a restful api

REST my Cake

CakeFest 2012 Manchester

Authentication

PublicApi-keyBasic AuthOAuth

Page 58: Cake fest 2012 create a restful api

REST my Cake

CakeFest 2012 Manchester

Authentication

public function getUser(CakeRequest $request) {if (!empty($this->settings['header'])) {

$token = $request->header($this->settings['header']);if ($token) {

return $this->_findUser($token, null);}

}if (!empty($request->query[$this->settings['parameter']])) {

$token = $request->query[$this->settings['parameter']];return $this->_findUser($token);

}return false;

}

Page 59: Cake fest 2012 create a restful api

REST my Cake

CakeFest 2012 Manchester

Versioning

/rest/v1

Page 60: Cake fest 2012 create a restful api

REST my Cake

CakeFest 2012 Manchester

THANKS