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
550
Обработка сложных 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
190
Featured
See All Featured
Building Flexible Design Systems
yeseniaperezcruz
330
40k
What the history of the web can teach us about the future of AI
inesmontani
PRO
1
490
Ethics towards AI in product and experience design
skipperchong
2
230
Google's AI Overviews - The New Search
badams
0
940
How to Think Like a Performance Engineer
csswizardry
28
2.5k
Mozcon NYC 2025: Stop Losing SEO Traffic
samtorres
0
180
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
254
22k
WENDY [Excerpt]
tessaabrams
9
37k
Public Speaking Without Barfing On Your Shoes - THAT 2023
reverentgeek
1
340
Pawsitive SEO: Lessons from My Dog (and Many Mistakes) on Thriving as a Consultant in the Age of AI
davidcarrasco
0
92
Avoiding the “Bad Training, Faster” Trap in the Age of AI
tmiket
0
110
The #1 spot is gone: here's how to win anyway
tamaranovitovic
2
990
Transcript
Dmitry Petrov
[email protected]
Обработка сложных 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": "
[email protected]
", "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": "
[email protected]
", "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