Handle complex POST/PATCH requests in RESTful API

58
Dmitry Petrov [email protected] Handle Complex POST/PATCH requests in RESTful API

description

Report with a speech on the 2012 sfcampua

Transcript of Handle complex POST/PATCH requests in RESTful API

Page 1: Handle complex POST/PATCH requests in RESTful API

Dmitry [email protected]

Handle Complex POST/PATCH requests in

RESTful API

Page 2: Handle complex POST/PATCH requests in RESTful API

ProFIT

Dmitry Petrov

The system of process control printing

Product Fulfillment and Information Tracking

Page 3: Handle complex POST/PATCH requests in RESTful API

ProFIT

Dmitry Petrov

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

Product Fulfillment and Information Tracking

Page 4: Handle complex POST/PATCH requests in RESTful API

RESTful API

Dmitry Petrov

~ 60 entity~100 API endpointsComplex business logic

RESTful API for ProFIT

Page 5: Handle complex POST/PATCH requests in RESTful API

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

Page 6: Handle complex POST/PATCH requests in RESTful API

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

Page 7: Handle complex POST/PATCH requests in RESTful API

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

Page 8: Handle complex POST/PATCH requests in RESTful API

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": "[email protected]",

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

"address": {

"country": "Russia",

"city": "Saratov",

"zip": 123456,

"street": "Vavilova",

"residentional": false

}

}

}

RESTful API, examples PATCH

Page 9: Handle complex POST/PATCH requests in RESTful API

Dmitry Petrov

Become thoughtful . . .

Page 10: Handle complex POST/PATCH requests in RESTful API

DTO

Dmitry Petrov

Data Transfer Object

DTO

attribute1: String

attribute2: String

Assembler

createDTO

updateDomainObjectserialize

deserialize

DomainObject1

attribute1: String

DomainObject2

attribute2: String

Page 11: Handle complex POST/PATCH requests in RESTful API

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

Page 12: Handle complex POST/PATCH requests in RESTful API

Dmitry Petrov

{

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

"note": null

}

{

"label": "epl string"

}

[

{

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

"types": [

"34-f-Type",

......

]

},

......

]

Examples of DTO

Page 13: Handle complex POST/PATCH requests in RESTful API

Dmitry Petrov

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

The benefits of using DTO pattern

Page 15: Handle complex POST/PATCH requests in RESTful API

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

Page 16: Handle complex POST/PATCH requests in RESTful API

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

Page 17: Handle complex POST/PATCH requests in RESTful API

Dmitry Petrov

JMSSerializerBundle & PATCH method

Page 18: Handle complex POST/PATCH requests in RESTful API

Dmitry Petrov

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

JMSSerializerBundle

Page 19: Handle complex POST/PATCH requests in RESTful API

MERGE

Dmitry Petrov

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

JMSSerializerBundle

Page 20: Handle complex POST/PATCH requests in RESTful API

Dmitry Petrov

Merging DTO

Page 21: Handle complex POST/PATCH requests in RESTful API

Dmitry Petrov

PATCH /api/orders/12Request:{

"client": {

"email": "",

"phone": null }

}

JMSSerializerBundle & PATCH method

Page 22: Handle complex POST/PATCH requests in RESTful API

Problems / Disadvantages

Dmitry Petrov

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

RESTful API, JMSSerializerBundle

Page 23: Handle complex POST/PATCH requests in RESTful API

Dmitry Petrov

SimpleThingsFormSerializerBundle

July 15, 2012

SimpleThingsFormSerializerBundle

Page 24: Handle complex POST/PATCH requests in RESTful API

Dmitry Petrov

SimpleThingsFormSerializerBundle

Page 25: Handle complex POST/PATCH requests in RESTful API

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

Page 26: Handle complex POST/PATCH requests in RESTful API

Problems / Disadvantages

Dmitry Petrov

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

The ideological aversionThe dirty mix *Type and *DTO

SimpleThingsFormSerializerBundle

Page 27: Handle complex POST/PATCH requests in RESTful API

Dmitry Petrov

Отпуск

Page 28: Handle complex POST/PATCH requests in RESTful API

Dmitry Petrov

Отпуск

Page 29: Handle complex POST/PATCH requests in RESTful API

Dmitry Petrov

Отпуск

Page 30: Handle complex POST/PATCH requests in RESTful API

Requirements

Dmitry Petrov

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

Reinvent the wheel

Page 31: Handle complex POST/PATCH requests in RESTful API

Assumptions

Dmitry Petrov

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

Reinvent the wheel

Page 33: Handle complex POST/PATCH requests in RESTful API

Benefits

Dmitry Petrov

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

SimpleSerializer

Page 34: Handle complex POST/PATCH requests in RESTful API

Dmitry Petrov

SimpleSerializer & POST / PATCH

Page 35: Handle complex POST/PATCH requests in RESTful API

Dmitry Petrov

SimpleSerializer & POST method

Page 36: Handle complex POST/PATCH requests in RESTful API

What? Where? When?

Dmitry Petrov

Parameters of requestsData transfer objectsBusiness logic

RESTful API, validation

Page 37: Handle complex POST/PATCH requests in RESTful API

Parameters of requests

Dmitry Petrov

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

RESTful API, validation

Page 38: Handle complex POST/PATCH requests in RESTful API

Routing requirements

Dmitry Petrov

RESTful API, validation

Page 39: Handle complex POST/PATCH requests in RESTful API

Dmitry Petrov

ParameterChecker

RESTful API, validation

Page 40: Handle complex POST/PATCH requests in RESTful API

Dmitry Petrov

RESTful API, validation

Page 41: Handle complex POST/PATCH requests in RESTful API

Dmitry Petrov

RESTful API, validation

Page 42: Handle complex POST/PATCH requests in RESTful API

Dmitry Petrov

AbstractRestController

RESTful API, validation

Page 43: Handle complex POST/PATCH requests in RESTful API

Dmitry Petrov

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

"client": {

"email": "",

"comment": "I'm hacker" }

}

Object:{

"id": 12,

"client": {

"firstname": "Dmitry",

"lastname": "Petrov",

"email": "[email protected]",

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

"address": {

"country": "Russia",

"city": "Saratov",

"zip": 123456,

"street": "Vavilova",

"residentional": false

}

}

}

RESTful API, validation

Page 44: Handle complex POST/PATCH requests in RESTful API

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

Page 45: Handle complex POST/PATCH requests in RESTful API

Dmitry Petrov

How, where and when to handle these situations?

RESTful API, validation

Page 47: Handle complex POST/PATCH requests in RESTful API

Dmitry Petrov

Disadvantages

ConventionalismDuplication of code Only works as filter

REST APIs with Symfony2: The Right Way

Page 48: Handle complex POST/PATCH requests in RESTful API

Dmitry Petrov

"Inteligent" deserialization

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

+Support groups

SimpleSerializer

Page 49: Handle complex POST/PATCH requests in RESTful API

Dmitry Petrov

RESTful API, handle of DTO

Page 50: Handle complex POST/PATCH requests in RESTful API

Dmitry Petrov

RESTful API, handle of domain object

Page 51: Handle complex POST/PATCH requests in RESTful API

Behat, PHPUnit

Dmitry Petrov

Controllers

Data access layerService layer

RESTful API, testing

Page 52: Handle complex POST/PATCH requests in RESTful API

Dmitry Petrov

RESTful API, Behat scenario

Page 53: Handle complex POST/PATCH requests in RESTful API

Problems

Dmitry Petrov

Run time:Behat ~ 90 minutesPHPUnit ~ 5 minutes

RESTful API, testing

Page 55: Handle complex POST/PATCH requests in RESTful API

WSSE Header

Dmitry Petrov

X-WSSE: UsernameToken Username="bob",

PasswordDigest="quR/EWLAV4xLf9Zqyw4pDmfV9OY=",

Nonce="d36e316282959a9ed4c89851497a717f",

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

RESTful API, authentication

Page 56: Handle complex POST/PATCH requests in RESTful API

Password digest

Dmitry Petrov

Base64 (SHA1 (Nonce + CreationTimestamp + Password))

RESTful API, authentication

Page 57: Handle complex POST/PATCH requests in RESTful API

Dmitry Petrov

RESTful API, The End

Page 58: Handle complex POST/PATCH requests in RESTful API

Any questions?

Dmitry Petrov

@old_fightmaster

RESTful API

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

Special thanks to ProFIT team