Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.Sign up
[WIP] General batch endpoint #1645
One of the major disadvantages of REST is that under certain circumstances you need a lot of requests to get to a desired state whether that is for data retrieval or data creation does not really matter. I think for data retrieval you should think about using GraphQL which we already have support for (awesome!).
So then I started thinking about how my batch endpoint should look like. Then, as I was thinking about the concept, I figured I could maybe build a general solution so I quickly put together this WIP to outline and allow for discussions
It's far from being complete but here's the idea:
If you want you can also add
This allows you to batch-create any data. You can even combine different endpoints in the same request! It's a general purpose API endpoint bringing maximum flexibility to API Platform. I would not recommend to mix multiple resources in one batch request but I think we should leave that decisions to the developers.
Here's a few things to consider, todo's or just remarks:
This is a very good idea and something we definitely need. Actually, this is on my todo list for a while and it’s awesome that you start working on this topic! Thank you.
I had a bit different implementation in mind. There is a specification for batch endpoints in the Odata protocol that is well designed: http://www.odata.org/documentation/odata-version-3-0/batch-processing/
The main idea is to send a multipart HTTP request to the batch endpoint that contains inner HTTP requests. It fits very well with the architecture of API Platform and Symfony, and allows to use 100% of the existing features of the framework (including content-negotiation).
It can be implemented this way:
OData also defines a way to use new entities in other requests in the same batch, it would be nice to support this in a second time.
There is almost everyhing we need in Symfony and API Platform to implement this, the only big missing part is... a HTTP parser. AFAIK, there is no PHP function nor popular library to parse a raw HTTP request. Symfony's HttpFoundation uses directly the PHP superglobals (
Regarding your specific use case, you can already use the "embedded relations" feature of API Platform like this:
API Platform will already take care of updating existing answers, and creating the new ones.
A batch endpoint will only be useful when reading or updating resources with no relations at all between them.
Hey, thanks for the feedback!
Basically, what Odata does, is what I meant with
I thought about it over the weekend and I have to admit that I don't fancy their solution. It is maybe the cleaner solution from a protocol perspective, yes. However, to me it's waaay to complicated to use. It would also require the client side to be able to build and parse http multipart requests/responses, not just API platform on the server side. So if you're for example using the API from within some JS with JSON, all you need is natively supported by JS and thus in any browser. So for batch requests you all of a sudden need an http parser, you need to understand http multipart requests with bounderies etc. I think acceptance of such and endpoint would be very low compared to a simple array of requests provided in the same data format you already work with for the rest of the API.
So in short: What Odata does is exactly the same as my proposal, it just makes use of HTTP spec possibilities. Normally I'd go for the spec but in that case I think I would go for the more straightforward solution because I'm pretty much convinced that acceptance would be way higher. And after all that's imho what an API is all about: making it easy for other developers to use and get the job done
BTW: Thank you for the hint regarding the relation, I might use that too, awesome!
There is an existing JS implementation for OData: https://stackoverflow.com/a/23805287/1352334
It looks cleaner to me to stick with HTTP (and reuse the Microsoft's R&D work) than re-creating a custom protocol.
@dunglas sorry it took so long to answer. I actually missed the notification. What I meant was, suppose a batch using something like Odata were to be implemented, would there be any way to make such an operation atomic? As in, if one of the requests fail, all of them must fail?
As Symfony now has a MIME component I wanted to see how we can take advantage of core development here or contribute to make that possible. I've discussed briefly with @fabpot at
So currently the MIME component supports generating MIME messages but not the other way around (no parser, yet). Moreover, multipart handling is the same for both HTTP and MIME so the logic can be shared there. Parsing HTTP is in fact pretty straight forward but for e-mails it's a lot harder due to encoding, maximum line lengths and a lot more.