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

Post on 27-Jun-2015

925 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

DESCRIPTION

Доклад с sfcampua 2012

TRANSCRIPT

Dmitry Petrovold.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

updateDomainObjectserialize

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

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/12Request:{

"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

SimpleSerializerSimpleSerializerBundle

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

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

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

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

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

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

Strict, Medium strict, Non-strict+

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

SimpleSerializer

Dmitry Petrov

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

Dmitry Petrov

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

Behat, PHPUnit

Dmitry Petrov

Контроллеры

Data access layerService layer

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

Dmitry Petrov

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

Проблемы

Dmitry Petrov

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

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/opensofthttps://github.com/fightmaster

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

top related