handle complex post/patch requests in restful api

Post on 25-Jan-2015

5.929 Views

Category:

Documents

3 Downloads

Preview:

Click to see full reader

DESCRIPTION

Report with a speech on the 2012 sfcampua

TRANSCRIPT

Dmitry Petrovold.fightmaster@gmail.com

Handle Complex POST/PATCH requests in

RESTful API

ProFIT

Dmitry Petrov

The system of process control printing

Product Fulfillment and Information Tracking

ProFIT

Dmitry Petrov

Daily:~ 1 000 orders~1 000 000 print productions1 hour of downtime ~ 25 000$

Product Fulfillment and Information Tracking

RESTful API

Dmitry Petrov

~ 60 entity~100 API endpointsComplex business logic

RESTful API for ProFIT

Dmitry Petrov

GET /api/orders/12/items/fg45sf54The server response:{

"id": "fg45sf54",

"url": "http://localhost/api/orders/12/items/fg45sf54",

"product": "business cards",

"quantity": 1000,

"previews": {

"front": {

"large": "http://localhost/large/front.jpg",

"medium": "http://localhost/medium/front.jpg",

"small": "http://localhost/small/front.jpg",

},

"back": {

"large": "http://localhost/large/back.jpg",

"medium": "http://localhost/medium/back.jpg",

"small": "http://localhost/small/back.jpg",

}

}

}

GET /api/orders/12The server response:{

"id": 12,

"url": "http://localhost/api/orders/12",

"client": {

"firstname": "Dmitry",

"lastname": "Petrov",

"email": "",

"phone": null,

"address": {

"country": "Russia",

"city": "Saratov",

"zip": 123456,

"street": "Vavilova",

"residentional": false

}

}

}

RESTful API, examples GET

Dmitry Petrov

GET /api/product-box-types/12-type/associationsThe server response:[

{

"id": 1,

"product": "business_cards",

"quantity": 1000

},

......

]

GET /api/machines/KARAT+1/hot-foldersThe server response:[

{

"path":"/home/somepath/",

"types": [

"34-f-Type",

"33-S-Type",

......

]

},

......

]

GET /api/press-sheets/134/labelThe server response:{

"label": "epl string"

}

RESTful API, examples GET

Dmitry Petrov

POST http://localhost/api/press-sheets/12/transitionBody of the request:{

"transition": "start:printing:front",

"note": null

}

POST http://localhost/api/orders,PUT http://localhost/api/orders/12Body of the request:{

"id": 12,

"client": {

"firstname": "Dmitry",

"lastname": "Petrov",

"email": "",

"phone": null,

"address": {

"country": "Russia",

"city": "Saratov",

"zip": 123456,

"street": "Vavilova",

"residentional": false

}

}

}

RESTful API, examples POST / PUT

Dmitry Petrov

PATCH http://localhost/api/orders/12Body of the request:{

"client": {

"email": "",

"phone": null

}

}

PATCH http://localhost/api/orders/12Body of the request:{

"client": {

"email": ""

},

"address": {

"street": "Vavilova",

"residentional": true

}

}

Object:{

"id": 12,

"client": {

"firstname": "Dmitry",

"lastname": "Petrov",

"email": "old.fightmaster@gmail.com",

"phone": "8-888-999",

"address": {

"country": "Russia",

"city": "Saratov",

"zip": 123456,

"street": "Vavilova",

"residentional": false

}

}

}

RESTful API, examples PATCH

Dmitry Petrov

Become thoughtful . . .

DTO

Dmitry Petrov

Data Transfer Object

DTO

attribute1: String

attribute2: String

Assembler

createDTO

updateDomainObjectserialize

deserialize

DomainObject1

attribute1: String

DomainObject2

attribute2: String

Dmitry Petrov

GET /api/orders/12The server response:{

"id": 12,

"url": "http://localhost/orders/12",

"client": {

"firstname": "Dmitry",

"lastname": "Petrov",

"email": "",

"phone": null,

"address": {

"country": "Russia",

"city": "Saratov",

"zip": 123456,

"street": "Vavilova",

"residentional": false

}

}

}

Examples of DTO

Dmitry Petrov

{

"transition": "start:printing:front",

"note": null

}

{

"label": "epl string"

}

[

{

"path":"/home/somepath/",

"types": [

"34-f-Type",

......

]

},

......

]

Examples of DTO

Dmitry Petrov

Reducing the number of queriesIndependence from API"Makes you think"

The benefits of using DTO pattern

Dmitry Petrov

GET /api/orders/12The server response:{

"id": 12,

"url": "http://localhost/api/orders/12",

"client": {

"firstname": "Dmitry",

"lastname": "Petrov",

"email": "",

"phone": null, "address": {

"country": "Russia",

"city": "Saratov",

"zip": 123456,

"street": "Vavilova",

"residentional": false

}

}

}

JMSSerializerBundle & GET method

Dmitry Petrov

POST /api/orders,Body of the request:{

"id": 12,

"client": {

"firstname": "Dmitry",

"lastname": "Petrov",

"email": "",

"phone": null,

"address": {

"country": "Russia",

"city": "Saratov",

"zip": 123456,

"street": "Vavilova",

"residentional": false

}

}

}

JMSSerializerBundle & POST method

Dmitry Petrov

JMSSerializerBundle & PATCH method

Dmitry Petrov

$this->deserialize($request, 'Rest\OrderDTO', 'json');

JMSSerializerBundle

MERGE

Dmitry Petrov

$this->merge($oldDTO, $newDTO);

JMSSerializerBundle

Dmitry Petrov

Merging DTO

Dmitry Petrov

PATCH /api/orders/12Request:{

"client": {

"email": "",

"phone": null }

}

JMSSerializerBundle & PATCH method

Problems / Disadvantages

Dmitry Petrov

GET - serialization of null valuesPATCH - deserialized into an objectPATCH - merge null valuesMERGE - a lot of useless code

RESTful API, JMSSerializerBundle

Dmitry Petrov

SimpleThingsFormSerializerBundle

July 15, 2012

SimpleThingsFormSerializerBundle

Dmitry Petrov

SimpleThingsFormSerializerBundle

Dmitry Petrov

GET /api/orders/12The server response:{

"id": "12",

"url": "http://localhost/orders/12",

"client": {

"firstname": "Dmitry",

"lastname": "Petrov",

"email": "",

"phone": "",

"address": {

"country": "Russia",

"city": "Saratov",

"zip": "123456",

"street": "Vavilova",

"residentional": "false"

}

}

}

SimpleThingsFormSerializerBundle

Problems / Disadvantages

Dmitry Petrov

Converting data into stringLack of support PATCH method (v. 2.0)

The ideological aversionThe dirty mix *Type and *DTO

SimpleThingsFormSerializerBundle

Dmitry Petrov

Отпуск

Dmitry Petrov

Отпуск

Dmitry Petrov

Отпуск

Requirements

Dmitry Petrov

(Un)Serialization of objectsPreservation of the type in dataMetadata cache

Reinvent the wheel

Assumptions

Dmitry Petrov

The output format is jsonMetadata is stored in ymlThere are get/set methods

Reinvent the wheel

Benefits

Dmitry Petrov

This is librarySeparation of serialization rules and formatAbsence voiced disadvantages"Inteligent" deserialization

SimpleSerializer

Dmitry Petrov

SimpleSerializer & POST / PATCH

Dmitry Petrov

SimpleSerializer & POST method

What? Where? When?

Dmitry Petrov

Parameters of requestsData transfer objectsBusiness logic

RESTful API, validation

Parameters of requests

Dmitry Petrov

/api/orders/12/api/boxes/BOX-1-1/api/orders?valid=true

RESTful API, validation

Routing requirements

Dmitry Petrov

RESTful API, validation

Dmitry Petrov

ParameterChecker

RESTful API, validation

Dmitry Petrov

RESTful API, validation

Dmitry Petrov

RESTful API, validation

Dmitry Petrov

AbstractRestController

RESTful API, validation

Dmitry Petrov

PATCH /api/orders/12Body of the request:{

"client": {

"email": "",

"comment": "I'm hacker" }

}

Object:{

"id": 12,

"client": {

"firstname": "Dmitry",

"lastname": "Petrov",

"email": "old.fightmaster@gmail.com",

"phone": "8-888-999",

"address": {

"country": "Russia",

"city": "Saratov",

"zip": 123456,

"street": "Vavilova",

"residentional": false

}

}

}

RESTful API, validation

Dmitry Petrov

POST /api/press-sheets/12/transitionBody of the request:{

"transition": "start:printing:front",

"note": null,

"comment": "I'm hacker"}

POST /api/press-sheets/12/transitionBody of the request:{

"transition": "start:printing:front",

"comment": "I'm hacker"}

Object:{

"transition": "start:printing:front",

"note": null

}

RESTful API, validation

Dmitry Petrov

How, where and when to handle these situations?

RESTful API, validation

Dmitry Petrov

Disadvantages

ConventionalismDuplication of code Only works as filter

REST APIs with Symfony2: The Right Way

Dmitry Petrov

"Inteligent" deserialization

3 modes of deserialization:Strict, Medium strict, Non-strict

+Support groups

SimpleSerializer

Dmitry Petrov

RESTful API, handle of DTO

Dmitry Petrov

RESTful API, handle of domain object

Behat, PHPUnit

Dmitry Petrov

Controllers

Data access layerService layer

RESTful API, testing

Dmitry Petrov

RESTful API, Behat scenario

Problems

Dmitry Petrov

Run time:Behat ~ 90 minutesPHPUnit ~ 5 minutes

RESTful API, testing

WSSE Header

Dmitry Petrov

X-WSSE: UsernameToken Username="bob",

PasswordDigest="quR/EWLAV4xLf9Zqyw4pDmfV9OY=",

Nonce="d36e316282959a9ed4c89851497a717f",

Created="2003-12-15T14:43:07Z"

RESTful API, authentication

Password digest

Dmitry Petrov

Base64 (SHA1 (Nonce + CreationTimestamp + Password))

RESTful API, authentication

Dmitry Petrov

RESTful API, The End

Any questions?

Dmitry Petrov

@old_fightmaster

RESTful API

https://github.com/opensofthttps://github.com/fightmaster

Special thanks to ProFIT team

top related