Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Handle complex POST/PATCH requests in RESTful API
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Dmitry Petrov
December 12, 2012
1
180
Handle complex POST/PATCH requests in RESTful API
Report with a speech on the 2012 sfcampua
Dmitry Petrov
December 12, 2012
Tweet
Share
More Decks by Dmitry Petrov
See All by Dmitry Petrov
Обработка сложных POST/PATCH запросов в RESTfu API
fightmaster
1
540
Featured
See All Featured
Design in an AI World
tapps
0
140
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
17k
Typedesign – Prime Four
hannesfritz
42
2.9k
Taking LLMs out of the black box: A practical guide to human-in-the-loop distillation
inesmontani
PRO
3
2k
The Pragmatic Product Professional
lauravandoore
37
7.1k
YesSQL, Process and Tooling at Scale
rocio
174
15k
DBのスキルで生き残る技術 - AI時代におけるテーブル設計の勘所
soudai
PRO
62
49k
Build The Right Thing And Hit Your Dates
maggiecrowley
38
3k
Believing is Seeing
oripsolob
1
53
What Being in a Rock Band Can Teach Us About Real World SEO
427marketing
0
170
How Software Deployment tools have changed in the past 20 years
geshan
0
32k
Evolving SEO for Evolving Search Engines
ryanjones
0
120
Transcript
Dmitry Petrov
[email protected]
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 productions 1 hour of downtime ~ 25 000$ Product Fulfillment and Information Tracking
RESTful API Dmitry Petrov ~ 60 entity ~100 API endpoints
Complex business logic RESTful API for ProFIT
Dmitry Petrov GET /api/orders/12/items/fg45sf54 The 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/12 The 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/associations The server response: [ { "id":
1, "product": "business_cards", "quantity": 1000 }, ...... ] GET /api/machines/KARAT+1/hot-folders The server response: [ { "path":"/home/somepath/", "types": [ "34-f-Type", "33-S-Type", ...... ] }, ...... ] GET /api/press-sheets/134/label The server response: { "label": "epl string" } RESTful API, examples GET
Dmitry Petrov POST http://localhost/api/press-sheets/12/transition Body of the request: { "transition":
"start:printing:front", "note": null } POST http://localhost/api/orders, PUT http://localhost/api/orders/12 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 } } } RESTful API, examples POST / PUT
Dmitry Petrov PATCH http://localhost/api/orders/12 Body of the request: { "client":
{ "email": "", "phone": null } } PATCH http://localhost/api/orders/12 Body 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
Dmitry Petrov Become thoughtful . . .
DTO Dmitry Petrov Data Transfer Object DTO attribute1: String attribute2:
String Assembler createDTO updateDomainObject serialize deserialize DomainObject1 attribute1: String DomainObject2 attribute2: String
Dmitry Petrov GET /api/orders/12 The 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 queries Independence from API
"Makes you think" The benefits of using DTO pattern
Dmitry Petrov FOSRestBundle JMSSerializerBundle LiipHelloBundle FOSCommentBundle Popular bundles and examples
Dmitry Petrov GET /api/orders/12 The 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/12 Request: { "client": { "email": "",
"phone": null } } JMSSerializerBundle & PATCH method
Problems / Disadvantages Dmitry Petrov GET - serialization of null
values PATCH - deserialized into an object PATCH - merge null values MERGE - a lot of useless code RESTful API, JMSSerializerBundle
Dmitry Petrov SimpleThingsFormSerializerBundle July 15, 2012 SimpleThingsFormSerializerBundle
Dmitry Petrov SimpleThingsFormSerializerBundle
Dmitry Petrov GET /api/orders/12 The 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 string Lack
of support PATCH method (v. 2.0) The ideological aversion The dirty mix *Type and *DTO SimpleThingsFormSerializerBundle
Dmitry Petrov Отпуск
Dmitry Petrov Отпуск
Dmitry Petrov Отпуск
Requirements Dmitry Petrov (Un)Serialization of objects Preservation of the type
in data Metadata cache Reinvent the wheel
Assumptions Dmitry Petrov The output format is json Metadata is
stored in yml There are get/set methods Reinvent the wheel
After 36 hours... train Saratov - Kiev is comming 30
hours Dmitry Petrov SimpleSerializer SimpleSerializerBundle Details can be found on the habr Reinvent the wheel
Benefits Dmitry Petrov This is library Separation of serialization rules
and format Absence voiced disadvantages "Inteligent" deserialization SimpleSerializer
Dmitry Petrov SimpleSerializer & POST / PATCH
Dmitry Petrov SimpleSerializer & POST method
What? Where? When? Dmitry Petrov Parameters of requests Data transfer
objects Business 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/12 Body 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
Dmitry Petrov POST /api/press-sheets/12/transition Body of the request: { "transition":
"start:printing:front", "note": null, "comment": "I'm hacker" } POST /api/press-sheets/12/transition Body 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 REST APIs with Symfony2: The Right Way
Dmitry Petrov Disadvantages Conventionalism Duplication 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 layer Service layer
RESTful API, testing
Dmitry Petrov RESTful API, Behat scenario
Problems Dmitry Petrov Run time: Behat ~ 90 minutes PHPUnit
~ 5 minutes RESTful API, testing
WSSE Dmitry Petrov Atom Authentication How to create a custom
Authentication Provider EscapeWSSEAuthenticationBundle (v. 2.0) MopaWSSEAuthenticationBundle (v. 2.1) RESTful API, authentication
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/opensoft https://github.com/fightmaster Special
thanks to ProFIT team