Обработка сложных POST/PATCH запросов в RESTful API
Upcoming SlideShare
Loading in...5
×
 

Обработка сложных POST/PATCH запросов в RESTful API

on

  • 965 views

Доклад с sfcampua 2012

Доклад с sfcampua 2012

Statistics

Views

Total Views
965
Views on SlideShare
954
Embed Views
11

Actions

Likes
2
Downloads
5
Comments
0

4 Embeds 11

https://twitter.com 5
http://www.sfexception.com 4
https://si0.twimg.com 1
http://twitter.com 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Обработка сложных POST/PATCH запросов в RESTful API Обработка сложных POST/PATCH запросов в RESTful API Presentation Transcript

  • Обработка сложныхPOST/PATCH запросов в RESTful API Dmitry Petrov old.fightmaster@gmail.com
  • Product Fulfillment and Information Tracking ProFIT Система управления производственными процессами типографии Dmitry Petrov
  • Product Fulfillment and Information Tracking ProFIT Ежедневно: ~ 1 000 заказов ~1 000 000 печатной продукции 1 час простоя ~ 25 000$ Dmitry Petrov
  • RESTful API для ProFIT RESTful API ~ 60 entity ~100 API endpoints Сложная бизнес логика Dmitry Petrov
  • RESTful API, примеры GET GET /api/orders/12 GET /api/orders/12/items/fg45sf54 Ответ сервера: Ответ сервера: { { "id": 12, "id": "fg45sf54", "url": "http://localhost/api/orders/12", "url": "http://localhost/api/orders/12/items/fg45sf54", "client": { "product": "business cards", "firstname": "Dmitry", "quantity": 1000, "lastname": "Petrov", "previews": { "email": "", "front": { "phone": null, "large": "http://localhost/large/front.jpg", "address": { "medium": "http://localhost/medium/front.jpg", "country": "Russia", "small": "http://localhost/small/front.jpg", "city": "Saratov", }, "zip": 123456, "back": { "street": "Vavilova", "large": "http://localhost/large/back.jpg", "residentional": false "medium": "http://localhost/medium/back.jpg", } "small": "http://localhost/small/back.jpg", } } } } } Dmitry Petrov
  • RESTful API, примеры GET GET /api/machines/KARAT+1/hot-folders GET /api/product-box-types/12-type/associations Ответ сервера: Ответ сервера: [ [ { { "path":"/home/somepath/", "id": 1, "types": [ "product": "business_cards", "34-f-Type", "quantity": 1000 "33-S-Type", }, ...... ...... ] ] }, ...... ] GET /api/press-sheets/134/label Ответ сервера: { "label": "epl string" } Dmitry Petrov
  • RESTful API, примеры POST / PUT POST http://localhost/api/orders, POST http://localhost/api/press-sheets/12/transition PUT http://localhost/api/orders/12 Тело запроса: Тело запроса: { { "transition": "start:printing:front", "id": 12, "note": null "client": { } "firstname": "Dmitry", "lastname": "Petrov", "email": "", "phone": null, "address": { "country": "Russia", "city": "Saratov", "zip": 123456, "street": "Vavilova", "residentional": false } } } Dmitry Petrov
  • RESTful API, примеры PATCH Объект: PATCH http://localhost/api/orders/12 { Тело запроса: "id": 12, { "client": { "client": { "firstname": "Dmitry", "email": "", "lastname": "Petrov", "phone": null "email": "old.fightmaster@gmail.com", } "phone": "8-888-999", } "address": { PATCH http://localhost/api/orders/12 "country": "Russia", Тело запроса: "city": "Saratov", { "zip": 123456, "client": { "street": "Vavilova", "email": "" "residentional": false }, } "address": { } "street": "Vavilova", } "residentional": true } } Dmitry Petrov
  • Призадумались . . . Dmitry Petrov
  • Data Transfer Object DTO DomainObject1 DTO attribute1: String Assembler attribute1: String attribute2: String createDTO updateDomainObject serialize deserialize DomainObject2 attribute2: String Dmitry Petrov
  • Примеры DTO 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 } } } Dmitry Petrov
  • Примеры DTO { "transition": "start:printing:front", "note": null } { "label": "epl string" } [ { "path":"/home/somepath/", "types": [ "34-f-Type", ...... ] }, ...... ] Dmitry Petrov
  • Преимущества паттерна DTOУменьшение количества запросовНезависимость от API"Заставляет думать" Dmitry Petrov
  • Популярные бандлы и примеры FOSRestBundle JMSSerializerBundle LiipHelloBundle FOSCommentBundle Dmitry Petrov
  • JMSSerializerBundle & GET метод 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 } } } Dmitry Petrov
  • JMSSerializerBundle & POST методPOST /api/orders,Тело запроса:{ "id": 12, "client": { "firstname": "Dmitry", "lastname": "Petrov", "email": "", "phone": null, "address": { "country": "Russia", "city": "Saratov", "zip": 123456, "street": "Vavilova", "residentional": false } }} Dmitry Petrov
  • JMSSerializerBundle & PATCH метод Dmitry Petrov
  • JMSSerializerBundle $this->deserialize($request, RestOrderDTO, json); Dmitry Petrov
  • JMSSerializerBundle MERGE $this->merge($oldDTO, $newDTO); Dmitry Petrov
  • Сливание DTO Dmitry Petrov
  • JMSSerializerBundle & PATCH методPATCH /api/orders/12Request:{ "client": { "email": "", "phone": null }} Dmitry Petrov
  • RESTful API, JMSSerializerBundle Проблемы / МинусыGET - сериализация null значенийPATCH - десериализация в объектPATCH - merge null значенийMERGE - много бесполезного кода Dmitry Petrov
  • SimpleThingsFormSerializerBundle SimpleThingsFormSerializerBundle 15 июля 2012 Dmitry Petrov
  • SimpleThingsFormSerializerBundle Dmitry Petrov
  • SimpleThingsFormSerializerBundleGET /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" } }} Dmitry Petrov
  • SimpleThingsFormSerializerBundle Проблемы / МинусыКонвертирование данных в stringОтсутствие поддержки PATCH (v. 2.0)Идеологическая неприязньГрязная смесь *Type и *DTO Dmitry Petrov
  • Отпуск Dmitry Petrov
  • Отпуск Dmitry Petrov
  • Отпуск Dmitry Petrov
  • Изобретаем велосипед Требования (Де)Сериализация объектов Сохранение типа у данных Кеширование метаданных Dmitry Petrov
  • Изобретаем велосипед Допущения Выходной формат json Метадата хранится в yml Всегда есть get/set методы Dmitry Petrov
  • Изобретаем велосипед Через 36 часов... поезд Саратов - Киев идет 30 часов SimpleSerializer SimpleSerializerBundle Подробности можно прочитать на хабре Dmitry Petrov
  • SimpleSerializer ПреимуществаБиблиотекаРазделение правил сериализации от форматаОтсутствие озвученных минусов"Интеллектуальная" десериализация Dmitry Petrov
  • SimpleSerializer & POST / PATCH Dmitry Petrov
  • SimpleSerializer & POST метод Dmitry Petrov
  • RESTful API, валидация Что? Где? Когда? Параметры запросов Объекты передачи данных Бизнес-логика Dmitry Petrov
  • RESTful API, валидация Параметры запросов /api/orders/12 /api/boxes/BOX-1-1 /api/orders?valid=true Dmitry Petrov
  • RESTful API, валидация Routing requirements Dmitry Petrov
  • RESTful API, валидация ParameterChecker Dmitry Petrov
  • RESTful API, валидация Dmitry Petrov
  • RESTful API, валидация Dmitry Petrov
  • RESTful API, валидация AbstractRestController Dmitry Petrov
  • RESTful API, валидация PATCH /api/orders/12 Объект: Тело запроса: { { "id": 12, "client": { "client": { "email": "", "firstname": "Dmitry", "comment": "Im hacker" "lastname": "Petrov", } "email": "old.fightmaster@gmail.com", } "phone": "8-888-999", "address": { "country": "Russia", "city": "Saratov", "zip": 123456, "street": "Vavilova", "residentional": false } } } Dmitry Petrov
  • RESTful API, валидация Объект: POST /api/press-sheets/12/transition { Тело запроса: "transition": "start:printing:front", { "note": null "transition": "start:printing:front", } "note": null, "comment": "Im hacker" } POST /api/press-sheets/12/transition Тело запроса: { "transition": "start:printing:front", "comment": "Im hacker" } Dmitry Petrov
  • RESTful API, валидация Как, где и когда обрабатывать эти ситуации? Dmitry Petrov
  • REST APIs with Symfony2: The Right Way Dmitry Petrov
  • REST APIs with Symfony2: The Right Way Недостатки Рутиность Дублирование кода Работает лишь как фильтр Dmitry Petrov
  • SimpleSerializer "Интеллектуальная" десериализация 3 режима десериализации: Strict, Medium strict, Non-strict + Поддержка групп Dmitry Petrov
  • RESTful API, обработка DTO Dmitry Petrov
  • RESTful API, обработка объекта Dmitry Petrov
  • RESTful API, тестирование Behat, PHPUnit Контроллеры Data access layer Service layer Dmitry Petrov
  • RESTful API, пример Behat сценария Dmitry Petrov
  • RESTful API, тестирование Проблемы Время выполнения: Behat ~ 90 минут PHPUnit ~ 5 минут Dmitry Petrov
  • RESTful API, аутентификация WSSEAtom AuthenticationHow to create a custom Authentication ProviderEscapeWSSEAuthenticationBundle (v. 2.0)MopaWSSEAuthenticationBundle (v. 2.1) Dmitry Petrov
  • RESTful API, аутентификация WSSE Header X-WSSE: UsernameToken Username="bob", PasswordDigest="quR/EWLAV4xLf9Zqyw4pDmfV9OY=", Nonce="d36e316282959a9ed4c89851497a717f", Created="2003-12-15T14:43:07Z" Dmitry Petrov
  • RESTful API, аутентификация Password digest Base64 (SHA1 (Nonce + CreationTimestamp + Password)) Dmitry Petrov
  • RESTful API, The End Dmitry Petrov
  • RESTful API Вопросы? @old_fightmaster https://github.com/opensoft https://github.com/fightmaster Отдельное спасибо команде ProFIT Dmitry Petrov