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
Serial(ize) killers, czyli jak popsuliśmy API
Serial(ize) killers, czyli jak popsuliśmy API

More Related Content

Similar to Serial(ize) killers, czyli jak popsuliśmy 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 Serial(ize) killers, czyli jak popsuliśmy 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

%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park masabamasaba
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfonteinmasabamasaba
 
%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in sowetomasabamasaba
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech studentsHimanshiGarg82
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024VictoriaMetrics
 
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...masabamasaba
 
Harnessing ChatGPT - Elevating Productivity in Today's Agile Environment
Harnessing ChatGPT  - Elevating Productivity in Today's Agile EnvironmentHarnessing ChatGPT  - Elevating Productivity in Today's Agile Environment
Harnessing ChatGPT - Elevating Productivity in Today's Agile EnvironmentVictorSzoltysek
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnAmarnathKambale
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension AidPhilip Schwarz
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsArshad QA
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️Delhi Call girls
 
tonesoftg
tonesoftgtonesoftg
tonesoftglanshi9
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...Shane Coughlan
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Steffen Staab
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrandmasabamasaba
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...Health
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisamasabamasaba
 
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Bert Jan Schrijver
 

Recently uploaded (20)

%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
 
%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
 
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
 
Harnessing ChatGPT - Elevating Productivity in Today's Agile Environment
Harnessing ChatGPT  - Elevating Productivity in Today's Agile EnvironmentHarnessing ChatGPT  - Elevating Productivity in Today's Agile Environment
Harnessing ChatGPT - Elevating Productivity in Today's Agile Environment
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
tonesoftg
tonesoftgtonesoftg
tonesoftg
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
 

Serial(ize) killers, czyli jak popsuliśmy 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