SlideShare a Scribd company logo
1 of 43
Download to read offline
SERIAL(IZE) KILLERS
czyli jak popsuliśmy API
Piotr Horzycki / Espeo Software / peterdev.pl
PROSTA ENCJA
class Product
{
public function __construct(
public readonly string $id,
public readonly string $name,
public readonly string $price,
public readonly string $editedBy,
) {
}
}
SERIALIZE(), CZYLI ZŁO
$code = serialize($product);
O:7:"Product":4:{s:2:"id";s:3:"123";s:4:"name";s:8:"Chainsaw";
s:5:"price";s:10:"EUR 123.45";s:8:"editedBy";s:4:"John";}
$product = unserialize($code);
MAŁY PATCH, DUŻY PROBLEM
ramsey/uuid 4.2.1
ramsey/uuid 4.2.2
$id = RamseyUuidUuid::uuid4();
C:35:"RamseyUuidLazyLazyUuidFromString":36:{23dc5ed8-4b73-4df8-9421-95e5c07a58e5}
O:35:"RamseyUuidLazyLazyUuidFromString":1:{s:6:"string";s:36:"4fdf0133-12be-4089-8fe5-45b4a3e2b
PROBLEM Z BEZPIECZEŃSTWEM
https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=unserialize
https://redfoxsec.com/blog/insecure-deserialization-in-php/
https://owasp.org/www-
community/vulnerabilities/PHP_Object_Injection
KIEDYŚ TO BYŁO...
{
"example": {
"key": "value"
}
}
$request = json_decode(file_get_contents('php://input'));
$price = $request['price'];
$name = $request['name'] ?? '';
KIEDY WYMYŚLONO SERIALIZER
$product = new Product('123', 'Chainsaw', 'EUR 123.45', 'John');
$json = $serializer->serialize($product);
{
"id": "123",
"name": "Chainsaw",
"price": "EUR 123.45",
"editedBy": "John"
}
$product = $serializer->deserialize($requestBody, Product::class, 'json');
KIEDY CHCEMY JESZCZE ORM
class Product
{
public function __construct(
#[ORMId, ORMColumn]
public readonly string $id,
#[ORMColumn]
public readonly string $name,
#[ORMColumn]
public readonly string $price,
#[ORMColumn]
public readonly string $editedBy,
) {
}
}
KIEDY FRONTEND CHCE COŚ ZMIENIĆ
class Product
{
public function __construct(
#[ORMId, ORMColumn]
public readonly string $id,
#[ORMColumn]
#[SerializedName("productName")]
public readonly string $name,
#[ORMColumn]
public readonly string $price,
#[ORMColumn]
public readonly string $editedBy,
) {
}
}
KIEDY FRONTEND CHCE RÓŻNE DANE
class Product
{
public function __construct(
#[ORMId, ORMColumn]
#[Groups(['admin', 'cart'])]
public readonly string $id,
#[ORMColumn]
#[Groups(['admin', 'cart'])]
#[SerializedName("productName")]
public readonly string $name,
#[ORMColumn]
#[Groups(['cart'])]
public readonly string $price,
#[ORMColumn]
#[Ignore]
public readonly string $editedBy,
) {
}
}
KIEDY FRONTEND CHCE COŚ EKSTRA
class Product
{
// ...
public function getUniversalAnswer(): int
{
return 42;
}
#[Ignore]
public function getImportantBusinessLogic(): int
{
return 2 * 2;
}
}
DORZUCANIE RZECZY POD STOŁEM
final class SneakyProductNormalizer implements NormalizerInterface
{
/** @param Product $object */
public function normalize(mixed $object, string $format = null, array $context = []): ar
{
return [
'id' => $object->id,
'name' => $object->name,
'price' => $object->price,
'extraField' => 2 * 2,
];
}
// ...
}
PERFORMANCE
100 pozycji na liście, 301 zapytań SQL...
ROZWIĄZANIE: DTO
class ProductAdminListDto
{
public function __construct(
public readonly string $id,
public readonly string $name,
) {
}
public static function fromEntity(Product $product): self
{
return new self($product->id, $product->name);
}
}
OBSŁUGA NULLI I WARTOŚCI
NIEZAINICJOWANYCH
class Product
{
public string $sku;
public ?string $rating = null;
}
OBSŁUGA NULLI I WARTOŚCI
NIEZAINICJOWANYCH
class Product
{
public string $sku;
public ?string $rating = null;
}
{
// "sku" pominięte, chyba że SKIP_UNINITIALIZED_VALUES = false
"rating": null // będzie pominięte dla SKIP_NULL_VALUES = true
}
HISTORIA TRUDNEJ MIGRACJI: JMS ->
SYMFONY
{
"type": "IP",
"value": "127.0.0.1",
"active": 123
}
HISTORIA TRUDNEJ MIGRACJI: JMS ->
SYMFONY
{
"type": "IP",
"value": "127.0.0.1",
"active": 123
}
$rule = $jms->deserialize($requestBody, Rule::class, 'json');
HISTORIA TRUDNEJ MIGRACJI: JMS ->
SYMFONY
{
"type": "IP",
"value": "127.0.0.1",
"active": 123
}
$rule = $jms->deserialize($requestBody, Rule::class, 'json');
W PHP mamy active === TRUE...
USZCZELNIAMY TYPY, PO CZYM KLIENT
ZGŁASZA BŁĄD...
Zadanie soft skill: wytłumacz klientowi, że się pomylił
{
"currency": "GBP",
"amount": "1234" // 🔥
}
CIĘŻKA PRZEPRAWA Z ENCJAMI
inne atrybuty JMS/Symfony
gąszcz ExclusionPolicy, Expose, Ignore
constructor property promotion, nulle itd.
BŁĘDY WALIDACJI TYPÓW W SYMFONY
try {
$dto = $serializer->deserialize($requestBody, Product::class, 'json', [
DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS => true,
]);
} catch (PartialDenormalizationException $e) {
$violations = new ConstraintViolationList();
foreach ($e->getErrors() as $exception) {
// ...
}
return $this->json($violations, 400);
}
https://symfony.com/doc/current/components/serializer.html#collecting-type-errors-while-denormalizing
DODANIE NOWEGO POLA, A INTEGRACJA
KLIENTA
class Notification
{
public function __construct(
public readonly string $paymentId,
public readonly string $status,
public readonly string $receivedAt,
) {
}
}
DEVELOPERS BE LIKE...
"He he... broken... wait a minute..."
DODANIE NOWEGO POLA, A INTEGRACJA
KLIENTA
class NotificationV2
{
public function __construct(
public readonly string $paymentId,
public readonly string $status,
public readonly string $receivedAt,
public readonly int $version = 2,
) {
}
}
ŹLE NAZWANE POLE OPCJONALNE
Walidacja przechodzi, ale funkcjonalność nie działa
Rozwiązanie: ALLOW_EXTRA_ATTRIBUTES = false
{
"currency": "GBP",
"amount": 1234,
"optionalFieldWithTypo": "foo" // 🔥
}
POZIOMY TESTÓW API
POZIOMY TESTÓW API
nie ma żadnych
POZIOMY TESTÓW API
nie ma żadnych
assert HTTP 200 (happy path)
POZIOMY TESTÓW API
nie ma żadnych
assert HTTP 200 (happy path)
assert HTTP 200 (błędne dane)
POZIOMY TESTÓW API
nie ma żadnych
assert HTTP 200 (happy path)
assert HTTP 200 (błędne dane)
assert JSON contains
POZIOMY TESTÓW API
nie ma żadnych
assert HTTP 200 (happy path)
assert HTTP 200 (błędne dane)
assert JSON contains
assert JSON path equals
POZIOMY TESTÓW API
nie ma żadnych
assert HTTP 200 (happy path)
assert HTTP 200 (błędne dane)
assert JSON contains
assert JSON path equals
assert database contains
POZIOMY TESTÓW API
nie ma żadnych
assert HTTP 200 (happy path)
assert HTTP 200 (błędne dane)
assert JSON contains
assert JSON path equals
assert database contains
assert no side effects
PODZIAŁ ODPOWIEDZIALNOŚCI MIĘDZY
WARSTWAMI TESTÓW
jednostkowe
integracyjne
API
E2E
DOKUMENTACJA? A KOMU TO POTRZEBNE...
rozjazd między OpenAPI a implementacją
brak przykładów w dokumentacji
ciągłe pytania od frontendowców
TESTY KONTRAKTÓW
Spectator (Laravel)
Pact.io
PODSUMOWANIE
unikać serialize()
nawet drobna różnica w API może popsuć integrację
testować API, łącznie z nietypowymi sytuacjami
DTO jako pośrednik między encjami a endpointami
wersjonowanie lub konfiguracja per klient
dokumentacja, która żyje
DZIĘKUJĘ :)
peterdev.pl
SERIALIZE KILLERS: How we broke our API
SERIALIZE KILLERS: How we broke our API

More Related Content

Similar to SERIALIZE KILLERS: How we broke our API

Security Meetup 22 октября. «PHP Unserialize Exploiting». Павел Топорков. Лаб...
Security Meetup 22 октября. «PHP Unserialize Exploiting». Павел Топорков. Лаб...Security Meetup 22 октября. «PHP Unserialize Exploiting». Павел Топорков. Лаб...
Security Meetup 22 октября. «PHP Unserialize Exploiting». Павел Топорков. Лаб...Mail.ru Group
 
Security Meetup 22 октября. «Реверс-инжиниринг в Enterprise». Алексей Секрето...
Security Meetup 22 октября. «Реверс-инжиниринг в Enterprise». Алексей Секрето...Security Meetup 22 октября. «Реверс-инжиниринг в Enterprise». Алексей Секрето...
Security Meetup 22 октября. «Реверс-инжиниринг в Enterprise». Алексей Секрето...Mail.ru Group
 
You code sucks, let's fix it
You code sucks, let's fix itYou code sucks, let's fix it
You code sucks, let's fix itRafael Dohms
 
Your code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnConYour code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnConRafael Dohms
 
Refactoring using Codeception
Refactoring using CodeceptionRefactoring using Codeception
Refactoring using CodeceptionJeroen van Dijk
 
Be RESTful (Symfony Camp 2008)
Be RESTful (Symfony Camp 2008)Be RESTful (Symfony Camp 2008)
Be RESTful (Symfony Camp 2008)Fabien Potencier
 
Unit testing with zend framework tek11
Unit testing with zend framework tek11Unit testing with zend framework tek11
Unit testing with zend framework tek11Michelangelo van Dam
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For BeginnersJonathan Wage
 
Symfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technologySymfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technologyDaniel Knell
 
WordPress Realtime - WordCamp São Paulo 2015
WordPress Realtime - WordCamp São Paulo 2015WordPress Realtime - WordCamp São Paulo 2015
WordPress Realtime - WordCamp São Paulo 2015Fernando Daciuk
 
WordPress REST API hacking
WordPress REST API hackingWordPress REST API hacking
WordPress REST API hackingJeroen van Dijk
 
Unit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBeneluxUnit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBeneluxMichelangelo van Dam
 
Advanced php testing in action
Advanced php testing in actionAdvanced php testing in action
Advanced php testing in actionJace Ju
 
Adding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy ApplicationsAdding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy ApplicationsSam Hennessy
 
Symfony2 - extending the console component
Symfony2 - extending the console componentSymfony2 - extending the console component
Symfony2 - extending the console componentHugo Hamon
 
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)James Titcumb
 
Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5Leonardo Proietti
 

Similar to SERIALIZE KILLERS: How we broke our API (20)

Intermediate PHP
Intermediate PHPIntermediate PHP
Intermediate PHP
 
Security Meetup 22 октября. «PHP Unserialize Exploiting». Павел Топорков. Лаб...
Security Meetup 22 октября. «PHP Unserialize Exploiting». Павел Топорков. Лаб...Security Meetup 22 октября. «PHP Unserialize Exploiting». Павел Топорков. Лаб...
Security Meetup 22 октября. «PHP Unserialize Exploiting». Павел Топорков. Лаб...
 
Security Meetup 22 октября. «Реверс-инжиниринг в Enterprise». Алексей Секрето...
Security Meetup 22 октября. «Реверс-инжиниринг в Enterprise». Алексей Секрето...Security Meetup 22 октября. «Реверс-инжиниринг в Enterprise». Алексей Секрето...
Security Meetup 22 октября. «Реверс-инжиниринг в Enterprise». Алексей Секрето...
 
You code sucks, let's fix it
You code sucks, let's fix itYou code sucks, let's fix it
You code sucks, let's fix it
 
Your code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnConYour code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnCon
 
Refactoring using Codeception
Refactoring using CodeceptionRefactoring using Codeception
Refactoring using Codeception
 
Be RESTful (Symfony Camp 2008)
Be RESTful (Symfony Camp 2008)Be RESTful (Symfony Camp 2008)
Be RESTful (Symfony Camp 2008)
 
Unit testing with zend framework tek11
Unit testing with zend framework tek11Unit testing with zend framework tek11
Unit testing with zend framework tek11
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For Beginners
 
Symfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technologySymfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technology
 
WordPress Realtime - WordCamp São Paulo 2015
WordPress Realtime - WordCamp São Paulo 2015WordPress Realtime - WordCamp São Paulo 2015
WordPress Realtime - WordCamp São Paulo 2015
 
WordPress REST API hacking
WordPress REST API hackingWordPress REST API hacking
WordPress REST API hacking
 
Oops in php
Oops in phpOops in php
Oops in php
 
Unit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBeneluxUnit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBenelux
 
Smelling your code
Smelling your codeSmelling your code
Smelling your code
 
Advanced php testing in action
Advanced php testing in actionAdvanced php testing in action
Advanced php testing in action
 
Adding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy ApplicationsAdding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy Applications
 
Symfony2 - extending the console component
Symfony2 - extending the console componentSymfony2 - extending the console component
Symfony2 - extending the console component
 
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
 
Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5
 

More from Piotr Horzycki

Mity, które blokują Twoją karierę
Mity, które blokują Twoją karieręMity, które blokują Twoją karierę
Mity, które blokują Twoją karieręPiotr Horzycki
 
Architecture tests: Setting a common standard
Architecture tests: Setting a common standardArchitecture tests: Setting a common standard
Architecture tests: Setting a common standardPiotr Horzycki
 
Software development myths that block your career
Software development myths that block your careerSoftware development myths that block your career
Software development myths that block your careerPiotr Horzycki
 
Software Composition Analysis in PHP
Software Composition Analysis in PHP Software Composition Analysis in PHP
Software Composition Analysis in PHP Piotr Horzycki
 
How to count money with Java and not lose it
How to count money with Java and not lose itHow to count money with Java and not lose it
How to count money with Java and not lose itPiotr Horzycki
 
How to count money using PHP and not lose money
How to count money using PHP and not lose moneyHow to count money using PHP and not lose money
How to count money using PHP and not lose moneyPiotr Horzycki
 
New kids on the block: Conducting technical onboarding
New kids on the block: Conducting technical onboardingNew kids on the block: Conducting technical onboarding
New kids on the block: Conducting technical onboardingPiotr Horzycki
 
Time-driven applications
Time-driven applicationsTime-driven applications
Time-driven applicationsPiotr Horzycki
 
Jak zacząć, aby nie żałować - czyli 50 twarzy PHP
Jak zacząć, aby nie żałować - czyli 50 twarzy PHPJak zacząć, aby nie żałować - czyli 50 twarzy PHP
Jak zacząć, aby nie żałować - czyli 50 twarzy PHPPiotr Horzycki
 

More from Piotr Horzycki (9)

Mity, które blokują Twoją karierę
Mity, które blokują Twoją karieręMity, które blokują Twoją karierę
Mity, które blokują Twoją karierę
 
Architecture tests: Setting a common standard
Architecture tests: Setting a common standardArchitecture tests: Setting a common standard
Architecture tests: Setting a common standard
 
Software development myths that block your career
Software development myths that block your careerSoftware development myths that block your career
Software development myths that block your career
 
Software Composition Analysis in PHP
Software Composition Analysis in PHP Software Composition Analysis in PHP
Software Composition Analysis in PHP
 
How to count money with Java and not lose it
How to count money with Java and not lose itHow to count money with Java and not lose it
How to count money with Java and not lose it
 
How to count money using PHP and not lose money
How to count money using PHP and not lose moneyHow to count money using PHP and not lose money
How to count money using PHP and not lose money
 
New kids on the block: Conducting technical onboarding
New kids on the block: Conducting technical onboardingNew kids on the block: Conducting technical onboarding
New kids on the block: Conducting technical onboarding
 
Time-driven applications
Time-driven applicationsTime-driven applications
Time-driven applications
 
Jak zacząć, aby nie żałować - czyli 50 twarzy PHP
Jak zacząć, aby nie żałować - czyli 50 twarzy PHPJak zacząć, aby nie żałować - czyli 50 twarzy PHP
Jak zacząć, aby nie żałować - czyli 50 twarzy PHP
 

Recently uploaded

Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...MyIntelliSource, Inc.
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...soniya singh
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideChristina Lin
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackVICTOR MAESTRE RAMIREZ
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsJhone kinadey
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxbodapatigopi8531
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providermohitmore19
 
Active Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfActive Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfCionsystems
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsAlberto González Trastoy
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfjoe51371421
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantAxelRicardoTrocheRiq
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfkalichargn70th171
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...kellynguyen01
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...harshavardhanraghave
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...gurkirankumar98700
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdfWave PLM
 
Test Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and BackendTest Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and BackendArshad QA
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationkaushalgiri8080
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
 

Recently uploaded (20)

Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStack
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptx
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
Active Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfActive Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdf
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdf
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service Consultant
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
 
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS LiveVip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 
Test Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and BackendTest Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and Backend
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanation
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 

SERIALIZE KILLERS: How we broke our API

  • 1. SERIAL(IZE) KILLERS czyli jak popsuliśmy API Piotr Horzycki / Espeo Software / peterdev.pl
  • 2.
  • 3. PROSTA ENCJA class Product { public function __construct( public readonly string $id, public readonly string $name, public readonly string $price, public readonly string $editedBy, ) { } }
  • 4. SERIALIZE(), CZYLI ZŁO $code = serialize($product); O:7:"Product":4:{s:2:"id";s:3:"123";s:4:"name";s:8:"Chainsaw"; s:5:"price";s:10:"EUR 123.45";s:8:"editedBy";s:4:"John";} $product = unserialize($code);
  • 5. MAŁY PATCH, DUŻY PROBLEM ramsey/uuid 4.2.1 ramsey/uuid 4.2.2 $id = RamseyUuidUuid::uuid4(); C:35:"RamseyUuidLazyLazyUuidFromString":36:{23dc5ed8-4b73-4df8-9421-95e5c07a58e5} O:35:"RamseyUuidLazyLazyUuidFromString":1:{s:6:"string";s:36:"4fdf0133-12be-4089-8fe5-45b4a3e2b
  • 7. KIEDYŚ TO BYŁO... { "example": { "key": "value" } } $request = json_decode(file_get_contents('php://input')); $price = $request['price']; $name = $request['name'] ?? '';
  • 8. KIEDY WYMYŚLONO SERIALIZER $product = new Product('123', 'Chainsaw', 'EUR 123.45', 'John'); $json = $serializer->serialize($product); { "id": "123", "name": "Chainsaw", "price": "EUR 123.45", "editedBy": "John" } $product = $serializer->deserialize($requestBody, Product::class, 'json');
  • 9. KIEDY CHCEMY JESZCZE ORM class Product { public function __construct( #[ORMId, ORMColumn] public readonly string $id, #[ORMColumn] public readonly string $name, #[ORMColumn] public readonly string $price, #[ORMColumn] public readonly string $editedBy, ) { } }
  • 10. KIEDY FRONTEND CHCE COŚ ZMIENIĆ class Product { public function __construct( #[ORMId, ORMColumn] public readonly string $id, #[ORMColumn] #[SerializedName("productName")] public readonly string $name, #[ORMColumn] public readonly string $price, #[ORMColumn] public readonly string $editedBy, ) { } }
  • 11. KIEDY FRONTEND CHCE RÓŻNE DANE class Product { public function __construct( #[ORMId, ORMColumn] #[Groups(['admin', 'cart'])] public readonly string $id, #[ORMColumn] #[Groups(['admin', 'cart'])] #[SerializedName("productName")] public readonly string $name, #[ORMColumn] #[Groups(['cart'])] public readonly string $price, #[ORMColumn] #[Ignore] public readonly string $editedBy, ) { } }
  • 12. KIEDY FRONTEND CHCE COŚ EKSTRA class Product { // ... public function getUniversalAnswer(): int { return 42; } #[Ignore] public function getImportantBusinessLogic(): int { return 2 * 2; } }
  • 13. DORZUCANIE RZECZY POD STOŁEM final class SneakyProductNormalizer implements NormalizerInterface { /** @param Product $object */ public function normalize(mixed $object, string $format = null, array $context = []): ar { return [ 'id' => $object->id, 'name' => $object->name, 'price' => $object->price, 'extraField' => 2 * 2, ]; } // ... }
  • 14. PERFORMANCE 100 pozycji na liście, 301 zapytań SQL...
  • 15. ROZWIĄZANIE: DTO class ProductAdminListDto { public function __construct( public readonly string $id, public readonly string $name, ) { } public static function fromEntity(Product $product): self { return new self($product->id, $product->name); } }
  • 16. OBSŁUGA NULLI I WARTOŚCI NIEZAINICJOWANYCH class Product { public string $sku; public ?string $rating = null; }
  • 17. OBSŁUGA NULLI I WARTOŚCI NIEZAINICJOWANYCH class Product { public string $sku; public ?string $rating = null; } { // "sku" pominięte, chyba że SKIP_UNINITIALIZED_VALUES = false "rating": null // będzie pominięte dla SKIP_NULL_VALUES = true }
  • 18. HISTORIA TRUDNEJ MIGRACJI: JMS -> SYMFONY { "type": "IP", "value": "127.0.0.1", "active": 123 }
  • 19. HISTORIA TRUDNEJ MIGRACJI: JMS -> SYMFONY { "type": "IP", "value": "127.0.0.1", "active": 123 } $rule = $jms->deserialize($requestBody, Rule::class, 'json');
  • 20. HISTORIA TRUDNEJ MIGRACJI: JMS -> SYMFONY { "type": "IP", "value": "127.0.0.1", "active": 123 } $rule = $jms->deserialize($requestBody, Rule::class, 'json'); W PHP mamy active === TRUE...
  • 21. USZCZELNIAMY TYPY, PO CZYM KLIENT ZGŁASZA BŁĄD... Zadanie soft skill: wytłumacz klientowi, że się pomylił { "currency": "GBP", "amount": "1234" // 🔥 }
  • 22. CIĘŻKA PRZEPRAWA Z ENCJAMI inne atrybuty JMS/Symfony gąszcz ExclusionPolicy, Expose, Ignore constructor property promotion, nulle itd.
  • 23. BŁĘDY WALIDACJI TYPÓW W SYMFONY try { $dto = $serializer->deserialize($requestBody, Product::class, 'json', [ DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS => true, ]); } catch (PartialDenormalizationException $e) { $violations = new ConstraintViolationList(); foreach ($e->getErrors() as $exception) { // ... } return $this->json($violations, 400); } https://symfony.com/doc/current/components/serializer.html#collecting-type-errors-while-denormalizing
  • 24. DODANIE NOWEGO POLA, A INTEGRACJA KLIENTA class Notification { public function __construct( public readonly string $paymentId, public readonly string $status, public readonly string $receivedAt, ) { } }
  • 25. DEVELOPERS BE LIKE... "He he... broken... wait a minute..."
  • 26. DODANIE NOWEGO POLA, A INTEGRACJA KLIENTA class NotificationV2 { public function __construct( public readonly string $paymentId, public readonly string $status, public readonly string $receivedAt, public readonly int $version = 2, ) { } }
  • 27. ŹLE NAZWANE POLE OPCJONALNE Walidacja przechodzi, ale funkcjonalność nie działa Rozwiązanie: ALLOW_EXTRA_ATTRIBUTES = false { "currency": "GBP", "amount": 1234, "optionalFieldWithTypo": "foo" // 🔥 }
  • 28.
  • 30. POZIOMY TESTÓW API nie ma żadnych
  • 31. POZIOMY TESTÓW API nie ma żadnych assert HTTP 200 (happy path)
  • 32. POZIOMY TESTÓW API nie ma żadnych assert HTTP 200 (happy path) assert HTTP 200 (błędne dane)
  • 33. POZIOMY TESTÓW API nie ma żadnych assert HTTP 200 (happy path) assert HTTP 200 (błędne dane) assert JSON contains
  • 34. POZIOMY TESTÓW API nie ma żadnych assert HTTP 200 (happy path) assert HTTP 200 (błędne dane) assert JSON contains assert JSON path equals
  • 35. POZIOMY TESTÓW API nie ma żadnych assert HTTP 200 (happy path) assert HTTP 200 (błędne dane) assert JSON contains assert JSON path equals assert database contains
  • 36. POZIOMY TESTÓW API nie ma żadnych assert HTTP 200 (happy path) assert HTTP 200 (błędne dane) assert JSON contains assert JSON path equals assert database contains assert no side effects
  • 37. PODZIAŁ ODPOWIEDZIALNOŚCI MIĘDZY WARSTWAMI TESTÓW jednostkowe integracyjne API E2E
  • 38. DOKUMENTACJA? A KOMU TO POTRZEBNE... rozjazd między OpenAPI a implementacją brak przykładów w dokumentacji ciągłe pytania od frontendowców
  • 40. PODSUMOWANIE unikać serialize() nawet drobna różnica w API może popsuć integrację testować API, łącznie z nietypowymi sytuacjami DTO jako pośrednik między encjami a endpointami wersjonowanie lub konfiguracja per klient dokumentacja, która żyje