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
Обработка сложных POST/PATCH запросов в RESTfu API
Search
Dmitry Petrov
December 03, 2012
1
500
Обработка сложных POST/PATCH запросов в RESTfu API
Доклад с выступления на sfcampua 2012
Dmitry Petrov
December 03, 2012
Tweet
Share
More Decks by Dmitry Petrov
See All by Dmitry Petrov
Handle complex POST/PATCH requests in RESTful API
fightmaster
1
180
Featured
See All Featured
A Tale of Four Properties
chriscoyier
158
23k
Keith and Marios Guide to Fast Websites
keithpitt
411
22k
The Pragmatic Product Professional
lauravandoore
33
6.5k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
PRO
17
1.1k
Designing for humans not robots
tammielis
251
25k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
32
2.2k
Producing Creativity
orderedlist
PRO
344
40k
How to Think Like a Performance Engineer
csswizardry
22
1.5k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
30
2.3k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
33
2.2k
RailsConf 2023
tenderlove
29
1k
The Cult of Friendly URLs
andyhume
78
6.3k
Transcript
Dmitry Petrov old.fightmaster@gmail.com Обработка сложных POST/PATCH запросов в RESTful API
ProFIT Dmitry Petrov Система управления производственными процессами типографии Product Fulfillment
and Information Tracking
ProFIT Dmitry Petrov Ежедневно: ~ 1 000 заказов ~1 000
000 печатной продукции 1 час простоя ~ 25 000$ Product Fulfillment and Information Tracking
RESTful API Dmitry Petrov ~ 60 entity ~100 API endpoints
Сложная бизнес логика RESTful API для ProFIT
Dmitry Petrov GET /api/orders/12/items/fg45sf54 Ответ сервера: { "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 Ответ сервера: { "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, примеры GET
Dmitry Petrov GET /api/product-box-types/12-type/associations Ответ сервера: [ { "id": 1,
"product": "business_cards", "quantity": 1000 }, ...... ] GET /api/machines/KARAT+1/hot-folders Ответ сервера: [ { "path":"/home/somepath/", "types": [ "34-f-Type", "33-S-Type", ...... ] }, ...... ] GET /api/press-sheets/134/label Ответ сервера: { "label": "epl string" } RESTful API, примеры GET
Dmitry Petrov POST http://localhost/api/press-sheets/12/transition Тело запроса: { "transition": "start:printing:front", "note":
null } POST http://localhost/api/orders, PUT http://localhost/api/orders/12 Тело запроса: { "id": 12, "client": { "firstname": "Dmitry", "lastname": "Petrov", "email": "", "phone": null, "address": { "country": "Russia", "city": "Saratov", "zip": 123456, "street": "Vavilova", "residentional": false } } } RESTful API, примеры POST / PUT
Dmitry Petrov PATCH http://localhost/api/orders/12 Тело запроса: { "client": { "email":
"", "phone": null } } PATCH http://localhost/api/orders/12 Тело запроса: { "client": { "email": "" }, "address": { "street": "Vavilova", "residentional": true } } Объект: { "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, примеры PATCH
Dmitry Petrov Призадумались . . .
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 Ответ сервера: { "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 } } } Примеры DTO
Dmitry Petrov { "transition": "start:printing:front", "note": null } { "label":
"epl string" } [ { "path":"/home/somepath/", "types": [ "34-f-Type", ...... ] }, ...... ] Примеры DTO
Dmitry Petrov Уменьшение количества запросов Независимость от API "Заставляет думать"
Преимущества паттерна DTO
Dmitry Petrov FOSRestBundle JMSSerializerBundle LiipHelloBundle FOSCommentBundle Популярные бандлы и примеры
Dmitry Petrov GET /api/orders/12 Ответ сервера: { "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 метод
Dmitry Petrov POST /api/orders, Тело запроса: { "id": 12, "client":
{ "firstname": "Dmitry", "lastname": "Petrov", "email": "", "phone": null, "address": { "country": "Russia", "city": "Saratov", "zip": 123456, "street": "Vavilova", "residentional": false } } } JMSSerializerBundle & POST метод
Dmitry Petrov JMSSerializerBundle & PATCH метод
Dmitry Petrov $this->deserialize($request, 'Rest\OrderDTO', 'json'); JMSSerializerBundle
MERGE Dmitry Petrov $this->merge($oldDTO, $newDTO); JMSSerializerBundle
Dmitry Petrov Сливание DTO
Dmitry Petrov PATCH /api/orders/12 Request: { "client": { "email": "",
"phone": null } } JMSSerializerBundle & PATCH метод
Проблемы / Минусы Dmitry Petrov GET - сериализация null значений
PATCH - десериализация в объект PATCH - merge null значений MERGE - много бесполезного кода RESTful API, JMSSerializerBundle
Dmitry Petrov SimpleThingsFormSerializerBundle 15 июля 2012 SimpleThingsFormSerializerBundle
Dmitry Petrov SimpleThingsFormSerializerBundle
Dmitry Petrov GET /api/orders/12 Ответ сервера: { "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
Проблемы / Минусы Dmitry Petrov Конвертирование данных в string Отсутствие
поддержки PATCH (v. 2.0) Идеологическая неприязнь Грязная смесь *Type и *DTO SimpleThingsFormSerializerBundle
Dmitry Petrov Отпуск
Dmitry Petrov Отпуск
Dmitry Petrov Отпуск
Требования Dmitry Petrov (Де)Сериализация объектов Сохранение типа у данных Кеширование
метаданных Изобретаем велосипед
Допущения Dmitry Petrov Выходной формат json Метадата хранится в yml
Всегда есть get/set методы Изобретаем велосипед
Через 36 часов... поезд Саратов - Киев идет 30 часов
Dmitry Petrov SimpleSerializer SimpleSerializerBundle Подробности можно прочитать на хабре Изобретаем велосипед
Преимущества Dmitry Petrov Библиотека Разделение правил сериализации от формата Отсутствие
озвученных минусов "Интеллектуальная" десериализация SimpleSerializer
Dmitry Petrov SimpleSerializer & POST / PATCH
Dmitry Petrov SimpleSerializer & POST метод
Что? Где? Когда? Dmitry Petrov Параметры запросов Объекты передачи данных
Бизнес-логика RESTful API, валидация
Параметры запросов Dmitry Petrov /api/orders/12 /api/boxes/BOX-1-1 /api/orders?valid=true RESTful API, валидация
Routing requirements Dmitry Petrov RESTful API, валидация
Dmitry Petrov ParameterChecker RESTful API, валидация
Dmitry Petrov RESTful API, валидация
Dmitry Petrov RESTful API, валидация
Dmitry Petrov AbstractRestController RESTful API, валидация
Dmitry Petrov PATCH /api/orders/12 Тело запроса: { "client": { "email":
"", "comment": "I'm hacker" } } Объект: { "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, валидация
Dmitry Petrov POST /api/press-sheets/12/transition Тело запроса: { "transition": "start:printing:front", "note":
null, "comment": "I'm hacker" } POST /api/press-sheets/12/transition Тело запроса: { "transition": "start:printing:front", "comment": "I'm hacker" } Объект: { "transition": "start:printing:front", "note": null } RESTful API, валидация
Dmitry Petrov Как, где и когда обрабатывать эти ситуации? RESTful
API, валидация
Dmitry Petrov REST APIs with Symfony2: The Right Way
Dmitry Petrov Недостатки Рутиность Дублирование кода Работает лишь как фильтр
REST APIs with Symfony2: The Right Way
Dmitry Petrov "Интеллектуальная" десериализация 3 режима десериализации: Strict, Medium strict,
Non-strict + Поддержка групп SimpleSerializer
Dmitry Petrov RESTful API, обработка DTO
Dmitry Petrov RESTful API, обработка объекта
Behat, PHPUnit Dmitry Petrov Контроллеры Data access layer Service layer
RESTful API, тестирование
Dmitry Petrov RESTful API, пример Behat сценария
Проблемы Dmitry Petrov Время выполнения: Behat ~ 90 минут PHPUnit
~ 5 минут RESTful API, тестирование
WSSE Dmitry Petrov Atom Authentication How to create a custom
Authentication Provider EscapeWSSEAuthenticationBundle (v. 2.0) MopaWSSEAuthenticationBundle (v. 2.1) RESTful API, аутентификация
WSSE Header Dmitry Petrov X-WSSE: UsernameToken Username="bob", PasswordDigest="quR/EWLAV4xLf9Zqyw4pDmfV9OY=", Nonce="d36e316282959a9ed4c89851497a717f", Created="2003-12-15T14:43:07Z"
RESTful API, аутентификация
Password digest Dmitry Petrov Base64 (SHA1 (Nonce + CreationTimestamp +
Password)) RESTful API, аутентификация
Dmitry Petrov RESTful API, The End
Вопросы? Dmitry Petrov @old_fightmaster RESTful API https://github.com/opensoft https://github.com/fightmaster Отдельное спасибо
команде ProFIT