Disclaimer: Though I’m listing here what make my life harder when using API Platform, I still consider it a great solution to build rapid CRUD prototypes. This article is addressed to those who want build a long-term api-based solution.
In principle there was FOSRestBundle, a shiny little magic box to create something similar to a REST API. Actually, there was too much magic in it..
And then API Platform came, and headaches with it.
Despite the documentation states that “Everything is fully customizable through a powerful event system and strong OOP”, the truth is that is nearly impossibile to customise deep behaviours and logic inside the api component and the choice to tightly couple it to the Symfony Serializer (probably the less powerful and poor of configuration options serializers I ever seen) make it even worse. But this is what I discovered only at the end of this incredible journey into API Platform..
The journey begins
The first thing I noted when I began to use API Platform was its no support for versioning. You can put a prefix in your path and pretend that is a versioning system, but the fact is that the tool does not help you at all. Ultimately I didn’t like versions in path: it is not so RESTy, I’d rather prefer to pass it through a request header (a custom one or an attribute of the Accept header).
So I began to start exploring services, normalizers, final classes with twelve (!) required dependencies and four optional dependencies to discover that everything in API Platform revolves around the OpenAPI specification.
OpenAPI, oh my!
I consider OpenAPI a great example on how NOT to write a specification. Partly because it tries to derive a protocol from an architectural standard (which REST is) and this is a nearly impossible task. And partly because of the limitations it puts upon a great designed protocol such as the HTTP.
For example: OpenAPI limits the HTTP methods you can use to the standardised ones (not even all the standardised methods, but this is another story), although the HTTP specification clearly states that a method is simply a group of US-ASCII characters. It does not even mandates the registration of non-standard methods to IANA, so why a specification used to define how to write your own API protocol should limit it?
Anyway, the extraordinary effort to produce an OpenAPI schema leads to the impossibility to have a versioned API for real. When I realised that, my mind blown up.
After overriding something like 14 services just to modify a single call contained in a final class which is required throughout all the API Platform codebase without specifying an interface, I started doubting..
The journey continues: DTOs, Serializer and validation
One of the most important things I learned from my work on monolithic projects was the use of DTOs and the rich model entities. They allowed me to avoid errors in database, simplifies the logics of dynamic forms and started to be a sort of holy grail of my projects: it was simply too convenient to use it.
I thought that maybe the DTOs could help me with this problem too. I was wrong.
API Platform does support DTOs, but not very well (to be honest, one of my colleagues told me that the DTOs support is better now, but when I tried, it was very very bad). There was not so much documentation, so I had to try to use them directly on code.
First try: write a simple DTO, declare it in input and output of the ApiResource annotation, add validation annotations on DTOs properties, write the transformer, send correct data, everything’s ok. Then I tried to pass invalid data: 500.
Umm.. I opened the web profiler, went to validation section and… surprise! API Platform called validation on the entity. WTF?!
That approach is bad for multiple reasons, but is obviously incompatible with the rich model entities as invalid data will throw exceptions when trying to set them into the entity. In addition, if a field is invalid on the entity, but is not present on the DTO (or is present with an aliased name), an error with an unknown field is returned to the client. No way!
Edit: someone told me that this behaviour is fixed now, but it was present at the time and anyway the DTOs support is still limited.
What makes it worse, is the use of Symfony Serializer which is impossible to replace. Its scarcity of configuration options (at the time a basic functionality such as the ignore attribute was not present) and the lack of control about the attributes to be exposed and the object construction was frustrating.
Additionally, the use of deserialisers which can throw an exception on invalid data makes everything really unstable and unreliable because those errors are returned to the client in a completely different way than the validation errors.
Headaches Platform: the end of the journey
What makes everything more and more complicated was the intensive use of hydra and jsonld. The aim of API Platform is to be the only one, the only API present in the system. But in the real world you are probably working on one API exposed by one service developed alongside other services and other APIs. These APIs are probably communicating each other and expose foreign references and data.
Producing only ONE documentation for the whole architecture can’t be done from one of these services as it cannot know the architecture of the other ones.
Out-of-scope functionalities (JWT authentication, admin generators, etc), bad designed filters (cannot be aliased for example), pagination with pages (which are a frontend concept) and a limited support for PATCH requests gave me only the confirmation of my doubts:
API Platform is not ready and is not designed to be a reliable API tool in a world of microservices.
So what?
So I started from scratch. Started a new Symfony project, begin writing stuff to have a powerful versioning system, to be compatible with rich model entities, without the limitations of OpenAPI and with DTOs to be a central point of the API architecture.
Now I decided to open my code and publish it on GitHub. I wanted this project to be a rock solid toolbox to write REST APIs which are maintenable in a long long term project, learning from all the things I don’t like in other API toolsets.
I called it Solido, and here’s the doc: https://solid-o.github.io/docs/
It’s obviously under active development and I’m looking for others to join me building a very strong, well written and useful open source API toolbox.
Thank you for reading,
A.
Top comments (0)