Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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

4f91cb7f6645e9a6a9458c720931f73b?s=47 Dmitry Petrov
December 03, 2012
370

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

Доклад с выступления на sfcampua 2012

4f91cb7f6645e9a6a9458c720931f73b?s=128

Dmitry Petrov

December 03, 2012
Tweet

Transcript

  1. Dmitry Petrov old.fightmaster@gmail.com Обработка сложных POST/PATCH запросов в RESTful API

  2. ProFIT Dmitry Petrov Система управления производственными процессами типографии Product Fulfillment

    and Information Tracking
  3. ProFIT Dmitry Petrov Ежедневно: ~ 1 000 заказов ~1 000

    000 печатной продукции 1 час простоя ~ 25 000$ Product Fulfillment and Information Tracking
  4. RESTful API Dmitry Petrov ~ 60 entity ~100 API endpoints

    Сложная бизнес логика RESTful API для ProFIT
  5. 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
  6. 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
  7. 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
  8. 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
  9. Dmitry Petrov Призадумались . . .

  10. DTO Dmitry Petrov Data Transfer Object DTO attribute1: String attribute2:

    String Assembler createDTO updateDomainObject serialize deserialize DomainObject1 attribute1: String DomainObject2 attribute2: String
  11. 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
  12. Dmitry Petrov { "transition": "start:printing:front", "note": null } { "label":

    "epl string" } [ { "path":"/home/somepath/", "types": [ "34-f-Type", ...... ] }, ...... ] Примеры DTO
  13. Dmitry Petrov Уменьшение количества запросов Независимость от API "Заставляет думать"

    Преимущества паттерна DTO
  14. Dmitry Petrov FOSRestBundle JMSSerializerBundle LiipHelloBundle FOSCommentBundle Популярные бандлы и примеры

  15. 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 метод
  16. 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 метод
  17. Dmitry Petrov JMSSerializerBundle & PATCH метод

  18. Dmitry Petrov $this->deserialize($request, 'Rest\OrderDTO', 'json'); JMSSerializerBundle

  19. MERGE Dmitry Petrov $this->merge($oldDTO, $newDTO); JMSSerializerBundle

  20. Dmitry Petrov Сливание DTO

  21. Dmitry Petrov PATCH /api/orders/12 Request: { "client": { "email": "",

    "phone": null } } JMSSerializerBundle & PATCH метод
  22. Проблемы / Минусы Dmitry Petrov GET - сериализация null значений

    PATCH - десериализация в объект PATCH - merge null значений MERGE - много бесполезного кода RESTful API, JMSSerializerBundle
  23. Dmitry Petrov SimpleThingsFormSerializerBundle 15 июля 2012 SimpleThingsFormSerializerBundle

  24. Dmitry Petrov SimpleThingsFormSerializerBundle

  25. 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
  26. Проблемы / Минусы Dmitry Petrov Конвертирование данных в string Отсутствие

    поддержки PATCH (v. 2.0) Идеологическая неприязнь Грязная смесь *Type и *DTO SimpleThingsFormSerializerBundle
  27. Dmitry Petrov Отпуск

  28. Dmitry Petrov Отпуск

  29. Dmitry Petrov Отпуск

  30. Требования Dmitry Petrov (Де)Сериализация объектов Сохранение типа у данных Кеширование

    метаданных Изобретаем велосипед
  31. Допущения Dmitry Petrov Выходной формат json Метадата хранится в yml

    Всегда есть get/set методы Изобретаем велосипед
  32. Через 36 часов... поезд Саратов - Киев идет 30 часов

    Dmitry Petrov SimpleSerializer SimpleSerializerBundle Подробности можно прочитать на хабре Изобретаем велосипед
  33. Преимущества Dmitry Petrov Библиотека Разделение правил сериализации от формата Отсутствие

    озвученных минусов "Интеллектуальная" десериализация SimpleSerializer
  34. Dmitry Petrov SimpleSerializer & POST / PATCH

  35. Dmitry Petrov SimpleSerializer & POST метод

  36. Что? Где? Когда? Dmitry Petrov Параметры запросов Объекты передачи данных

    Бизнес-логика RESTful API, валидация
  37. Параметры запросов Dmitry Petrov /api/orders/12 /api/boxes/BOX-1-1 /api/orders?valid=true RESTful API, валидация

  38. Routing requirements Dmitry Petrov RESTful API, валидация

  39. Dmitry Petrov ParameterChecker RESTful API, валидация

  40. Dmitry Petrov RESTful API, валидация

  41. Dmitry Petrov RESTful API, валидация

  42. Dmitry Petrov AbstractRestController RESTful API, валидация

  43. 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, валидация
  44. 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, валидация
  45. Dmitry Petrov Как, где и когда обрабатывать эти ситуации? RESTful

    API, валидация
  46. Dmitry Petrov REST APIs with Symfony2: The Right Way

  47. Dmitry Petrov Недостатки Рутиность Дублирование кода Работает лишь как фильтр

    REST APIs with Symfony2: The Right Way
  48. Dmitry Petrov "Интеллектуальная" десериализация 3 режима десериализации: Strict, Medium strict,

    Non-strict + Поддержка групп SimpleSerializer
  49. Dmitry Petrov RESTful API, обработка DTO

  50. Dmitry Petrov RESTful API, обработка объекта

  51. Behat, PHPUnit Dmitry Petrov Контроллеры Data access layer Service layer

    RESTful API, тестирование
  52. Dmitry Petrov RESTful API, пример Behat сценария

  53. Проблемы Dmitry Petrov Время выполнения: Behat ~ 90 минут PHPUnit

    ~ 5 минут RESTful API, тестирование
  54. WSSE Dmitry Petrov Atom Authentication How to create a custom

    Authentication Provider EscapeWSSEAuthenticationBundle (v. 2.0) MopaWSSEAuthenticationBundle (v. 2.1) RESTful API, аутентификация
  55. WSSE Header Dmitry Petrov X-WSSE: UsernameToken Username="bob", PasswordDigest="quR/EWLAV4xLf9Zqyw4pDmfV9OY=", Nonce="d36e316282959a9ed4c89851497a717f", Created="2003-12-15T14:43:07Z"

    RESTful API, аутентификация
  56. Password digest Dmitry Petrov Base64 (SHA1 (Nonce + CreationTimestamp +

    Password)) RESTful API, аутентификация
  57. Dmitry Petrov RESTful API, The End

  58. Вопросы? Dmitry Petrov @old_fightmaster RESTful API https://github.com/opensoft https://github.com/fightmaster Отдельное спасибо

    команде ProFIT