Обработка сложных post/patch запросов в restful api

58
Dmitry Petrov [email protected] Обработка сложных POST/PATCH запросов в RESTful API

Upload: fightmaster

Post on 27-Jun-2015

925 views

Category:

Documents


0 download

DESCRIPTION

Доклад с sfcampua 2012

TRANSCRIPT

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

Dmitry [email protected]

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

RESTful API

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

ProFIT

Dmitry Petrov

Система управления производственными

процессами типографии

Product Fulfillment and Information Tracking

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

ProFIT

Dmitry Petrov

Ежедневно:~ 1 000 заказов~1 000 000 печатной продукции1 час простоя ~ 25 000$

Product Fulfillment and Information Tracking

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

RESTful API

Dmitry Petrov

~ 60 entity~100 API endpointsСложная бизнес логика

RESTful API для ProFIT

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

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

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

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

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

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

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

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

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

Dmitry Petrov

Призадумались . . .

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

DTO

Dmitry Petrov

Data Transfer Object

DTO

attribute1: String

attribute2: String

Assembler

createDTO

updateDomainObjectserialize

deserialize

DomainObject1

attribute1: String

DomainObject2

attribute2: String

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

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

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

Dmitry Petrov

{

"transition": "start:printing:front",

"note": null

}

{

"label": "epl string"

}

[

{

"path":"/home/somepath/",

"types": [

"34-f-Type",

......

]

},

......

]

Примеры DTO

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

Dmitry Petrov

Уменьшение количества запросовНезависимость от API"Заставляет думать"

Преимущества паттерна DTO

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

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 метод

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

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 метод

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

Dmitry Petrov

JMSSerializerBundle & PATCH метод

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

Dmitry Petrov

$this->deserialize($request, 'Rest\OrderDTO', 'json');

JMSSerializerBundle

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

MERGE

Dmitry Petrov

$this->merge($oldDTO, $newDTO);

JMSSerializerBundle

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

Dmitry Petrov

Сливание DTO

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

Dmitry Petrov

PATCH /api/orders/12Request:{

"client": {

"email": "",

"phone": null }

}

JMSSerializerBundle & PATCH метод

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

Проблемы / Минусы

Dmitry Petrov

GET - сериализация null значенийPATCH - десериализация в объектPATCH - merge null значенийMERGE - много бесполезного кода

RESTful API, JMSSerializerBundle

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

Dmitry Petrov

SimpleThingsFormSerializerBundle

15 июля 2012

SimpleThingsFormSerializerBundle

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

Dmitry Petrov

SimpleThingsFormSerializerBundle

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

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

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

Проблемы / Минусы

Dmitry Petrov

Конвертирование данных в stringОтсутствие поддержки PATCH (v. 2.0)

Идеологическая неприязньГрязная смесь *Type и *DTO

SimpleThingsFormSerializerBundle

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

Dmitry Petrov

Отпуск

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

Dmitry Petrov

Отпуск

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

Dmitry Petrov

Отпуск

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

Требования

Dmitry Petrov

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

Изобретаем велосипед

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

Допущения

Dmitry Petrov

Выходной формат jsonМетадата хранится в ymlВсегда есть get/set методы

Изобретаем велосипед

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

Через 36 часов...поезд Саратов - Киев идет 30 часов

Dmitry Petrov

SimpleSerializerSimpleSerializerBundle

Подробности можно прочитать на хабре

Изобретаем велосипед

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

Преимущества

Dmitry Petrov

БиблиотекаРазделение правил сериализации от форматаОтсутствие озвученных минусов"Интеллектуальная" десериализация

SimpleSerializer

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

Dmitry Petrov

SimpleSerializer & POST / PATCH

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

Dmitry Petrov

SimpleSerializer & POST метод

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

Что? Где? Когда?

Dmitry Petrov

Параметры запросовОбъекты передачи данныхБизнес-логика

RESTful API, валидация

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

Параметры запросов

Dmitry Petrov

/api/orders/12/api/boxes/BOX-1-1/api/orders?valid=true

RESTful API, валидация

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

Routing requirements

Dmitry Petrov

RESTful API, валидация

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

Dmitry Petrov

ParameterChecker

RESTful API, валидация

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

Dmitry Petrov

RESTful API, валидация

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

Dmitry Petrov

RESTful API, валидация

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

Dmitry Petrov

AbstractRestController

RESTful API, валидация

Page 43: Обработка сложных POST/PATCH запросов в 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, валидация

Page 44: Обработка сложных POST/PATCH запросов в 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, валидация

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

Dmitry Petrov

Как, где и когда обрабатывать эти ситуации?

RESTful API, валидация

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

Dmitry Petrov

Недостатки

РутиностьДублирование кода Работает лишь как фильтр

REST APIs with Symfony2: The Right Way

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

Dmitry Petrov

"Интеллектуальная"

десериализация3 режима десериализации:

Strict, Medium strict, Non-strict+

Поддержка групп

SimpleSerializer

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

Dmitry Petrov

RESTful API, обработка DTO

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

Dmitry Petrov

RESTful API, обработка объекта

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

Behat, PHPUnit

Dmitry Petrov

Контроллеры

Data access layerService layer

RESTful API, тестирование

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

Dmitry Petrov

RESTful API, пример Behat сценария

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

Проблемы

Dmitry Petrov

Время выполнения:Behat ~ 90 минутPHPUnit ~ 5 минут

RESTful API, тестирование

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

WSSE Header

Dmitry Petrov

X-WSSE: UsernameToken Username="bob",

PasswordDigest="quR/EWLAV4xLf9Zqyw4pDmfV9OY=",

Nonce="d36e316282959a9ed4c89851497a717f",

Created="2003-12-15T14:43:07Z"

RESTful API, аутентификация

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

Password digest

Dmitry Petrov

Base64 (SHA1 (Nonce + CreationTimestamp + Password))

RESTful API, аутентификация

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

Dmitry Petrov

RESTful API, The End

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

Вопросы?

Dmitry Petrov

@old_fightmaster

RESTful API

https://github.com/opensofthttps://github.com/fightmaster

Отдельное спасибо команде ProFIT