It’s been almost a year since we released the first stable version of HTTPlug so I felt like it’s time to look back on what we’ve done so far and what’s still ahead of us.
If you don’t know what HTTPlug is: it’s an HTTP Client abstraction for PHP created by the PHP HTTP group. Th main goal is to let developers build HTTP-based libraries without relying on an actual implementation, thus avoiding the vendor lock-in. It can also prevent conflicts between libraries, since the user only need to install one HTTP Client and not one for each library (eg. Guzzle 5 and 6). Together with HTTPlug comes a list of adapters for already existing and well-known HTTP Clients like Guzzle, Buzz, etc.
It all started with a package called Ivory HTTP Adapter (created by Eric Geloen) which provided adapters for all the commonly used HTTP Clients out there. PSR-7 was still a proposal (already third or fourth times completely rewritten version), but Ivory already had support for it making it extremely useful and causing a lot of headaches to Eric because of the frequent changes. The package was quite huge and massive with tons of features, but with lots of dependencies as well. It was only a matter of time until someone suggested to split the big package into smaller ones. The discussion escalated quite quickly (literally, within hours)… and PHP HTTP was born.
HTTP adapt…client abstraction
In the beginning we were very excited, especially because PSR-7 came out soon after the group was formed.
That resulted in a long planning phase and constantly changing goals, ideas.
The biggest one was changing the goal from splitting adapters to rewritting as a client abstraction.
In order to achieve that we dropped many things (configurable requests, HTTP Verb methods, etc) and tried to find the smallest possible API:
send method accepting a PSR-7 request. We not just removed, but also added features:
we added async support to the abstraction which later served as a base for the plugin system
After changing the goal we also wanted to find a better name than HTTP Client: HTTPlug came true as well.
Although we had to narrow down what we include in the abstraction, we did not want to completely drop all the features inherited from Ivory,
so we built small utility packages on top of HTTPlug for most of them. As we added more and more features the number of packages became unmaintainable,
not to mention how ugly application
composer.json files became (with many PHP HTTP packages in it).
We had quite a few discussions about the perfect solution. In Ivory we already learned that putting everything in one package is a no-go,
but tons of packages didn’t work either so we agreed to merge as much as packages possible, but to avoid having too much dependencies,
we only merged the ones without external (non-PHP HTTP) dependencies. As a result there are two main “utility” packages now:
- message: Contains tools for working with HTTP Messages (authentication, encoding, compression, factories, etc)
- client-common: Contains common client implementations (Batch client, HTTP Methods client, sync/async emulation) and the foundation of the plugin system with a few basic plugins
We received many (and I am happy to say that mostly positive) feedback from the community. Of course we tried to listen to complaints as well which were extremely helpful to make the whole HTTPlug ecosystem more userfriendly.
A huge number of the reports were related to our discovery layer and Puli which identifies itself as “a universal package system for PHP”. Puli made it easy to automatically register resources HTTP clients and factories) in the discovery layer, but according to the reporters it was a quite massive dependency and it wasn’t easy to set up in applications at all. This is why we decided to make Puli optional.
As for adoption: We are proud that well-known packages (Geocoder, Mailgun SDK, FOS HTTP Cache to name a few) started to use HTTPlug. Many thanks to our team member Tobias Nyholm for that, since most of the adoption is his contribution to these projects.
What comes next?
Although HTTPlug comes with a list of adapters, the ideal case would be if clients implemented it directly, therefore we are actively working on a PSR proposal for the sync client interface. Since it is already quite stable most of the work is to write down a proper specification and explain all the design decisions. We are very close to finish this work and form a working group which will discuss the current state, challenge our decisions once more to see if they where the best decisions we could make and make the proposal to the FIG.
We decided to create separate PSRs for the two clients, because the async one requires a promise/event loop interface as well. HTTPlug comes with it’s own but standardizing it as part of the client wouldn’t really be a good idea, not to mention that the PHP Asynchronous Interoperability Group is already working on it. We are looking at the options at the moment and hopefully a proposal for the async client will follow the sync one shortly.
Since August the group is also responsible for the maintenance of Guzzle, so if the PSR becomes a thing (in agreement with it’s author Michael Dowling) we will make sure that Guzzle will comply with it as soon as possible.
Many people are concerned about the maintenance promise and the stability of the interfaces, especially now that the PSR is on it’s way. As I already mentioned before, the interfaces are quite simple and stable (thanks to the long beta testing phase which allowed us to battle test the code and correct the design mistakes), so hopefully it will be accepted as is. If so, HTTPlug will extend the PSR interface. But if not, HTTPlug will still be maintained as there are already major projects relying on it.
This was quite an interesting first year for the project and as far as I can see, we still have many interesting stuff to do ahead of us. Maybe things will proceed a bit slower (especially the PSR), but we continue actively maintaining and supporting the project.