-
28 votes
-
Disclosure of a vulnerability in AI Dungeon that enabled accessing all users' private adventures, scenarios, and posts via its GraphQL API
16 votes -
The Contentful DevRel team, with guests from Microsoft and Azure, are hosting weekly educational livestreams on GraphQL, React and more. Might be interesting if you are working with GraphQL!
4 votes -
How and why GraphQL will influence the SourceHut alpha
5 votes -
Ask Tildes: Design practices for retrieving dozens (or hundreds) of related records over a RESTful API
I'm looking for some feedback on a feasible mechanism for structuring a few API endpoints where a purely RFC-spec compliant REST API wouldn't suffice. I have an endpoint which returns $child...
I'm looking for some feedback on a feasible mechanism for structuring a few API endpoints where a purely RFC-spec compliant REST API wouldn't suffice.
I have an endpoint which returns $child entries for a $parent resource, let's call it:
/api/parent/:parentId/children
. There could be anywhere from a dozen to several hundred children returned from this call. From here, achild
entity is related to a singleuserOrganization
, which itself is a pivoting entity on a singleuser
. The relationship between achild
anduser
is not strictly transitive, but can eachchild
only has oneuserOrganization
which only has oneuser
, so it is trivial to reach auser
from achild
resource.Given this, the data I need for the particular request involves retrieving all
user
's for aparent
. The obvious, and incorrect solution to the problem is to make the request mentioned above, and then iterate through and make an API request to retrieve eachuser
. This is less than very good as this would obviously be up to several hundred API calls.There's a few more scalable solutions that could solve this problem, so any input on these ideas is great; but if you have a better proposal that also works, I'm keen to explore that!
Include
user
relationships in the call by default.This certainly does solve the problem, but it's also pumping down a load of data I don't necessarily need. This would probably 2x the amount of bytes travelling along the wire, and in 8 out of 10 calls, that extra data isn't needed.
Have a separate
/api/parent/:parentId/users
call.Another option that partially solves the issue: I need data from both the
child
and theuser
to format this view, so I'd still need to make the initial call I documented earlier. Semantically, it feels a bit odd to have this as a resource because I don't consider auser
to be nested under aparent
in terms of database topology.Keep the original call, but add a query parameter to fetch the extra data
This comes across as the 'least worst' idea objectively, in terms of flexibility and design. Through the addition of the query parameter, you could optionally retrieve the relationship's data. This seems brittle and doesn't scale well to other endpoints where it could be useful though.
Utilize a Stripe
expands
-style query parameter.Stripe implements the ability to retrieve all related records from an API endpoint by specifying the relations as strings. This is essentially the same as the above answer, but is scaled to all available API endpoints. I love this idea, but implementing it in a secure way seems fraught with disaster. For example, this is a multi-tenancied application, and it would be trivial to request
userOrganization.user.organizations.users
. This would retrieve all other organisations for the user, and their users! This is because my implementation ofexpands
simply utilises the ORM of my choice to perform a database join, and of course the database has no knowledge about application tenancy!
Now, I do realise this problem could easily be solved by implementing a GraphQL API server, which I have done in the past, but unfortunately time and workload constraints dictate implementing a GraphQL-based solution is infeasible. As much as I like GraphQL, I'm not as proficient in that area as compared to implementing high quality traditional APIs, and the applications I'm working on at the moment are focusing on choosing boring technology, and not using excessive innovation tokens.
Furthermore, I do consider the conceptuals around REST APIs to be more of an aspirational sliding scale, rather than a well defined physical entity, because let's face it, the majority of popular APIs today aren't REST-compliant, even Stripe's isn't, and it's usually both financially healthier and feature-rich to choose a development path that results in a rough product that can be refined later, than aiming for a perfect initial release. All this said, I don't mind proposals or solutions to my problem that are "good enough". As long as they aren't too hacky! :)
10 votes