5 ms·
When doing something like `student/1245/courses` there will certainly be a scenario where you want a list of courses on their own as well. If planning ahead, d
by tchow 9y ago
When doing something like `student/1245/courses` there will certainly be a scenario where you want a list of courses on their own as well.
If planning ahead, does that warrant designing your route such as:
`/courses` where you get a list of courses and
`/courses?studentId=12345` Where you get courses scoped to a student...
Or is it better to just recreate a separate route such that you have /courses AND student/2345/courses?
Im concerned that the latter results in duplication of code and possibly more confusion (ie not clear if the API require POST to /courses or /student/12345/courses to create a course for a student ) while the former results may cause (lack of) caching problems.
Suggestions?
- idkfa 9y agojust drop this REST hype altogether and use adequate protocols for communication
- pyre 9y agoAs in design a custom TCP/IP protocol for every application?
- stingraycharles 9y agoI think there are a few GraphQL enthusiasts entering this thread right now, which has its own merits, but can live perfectly next to REST.
- konschubert 9y agoIn my company we use graphql for getting, and REST for all other operations. Might be an antipattern, but has served us well. We're also using a special flavor of graphql that returns the data as flat dictionaries instead of deeply nested dictionaries. Whether you need that or not of course depends on the client design.
- kuschku 9y agoAs in using GraphQL for this purpose, I presume. Or even offering an SQL-API. Seems more ideal than overly complicated URL schemes.
- laumars 9y agoIf it's an API then you could bypass the aforementioned constraints of spitting your request up by URI "directories" and instead have your query's parameters passed via form data or serialised as JSON* in the HTTP request body. URIs are easier to deal with but not _that_ much easier if you're programmatically sending the requests as one might expect to do with an API * Other data formats also exist
- tchow 9y agoAdding stuff to a request body in GET is considered an antipattern
- laumars 9y agoIf your APIs are login sensitive then you'd want your APIs to be POST requests anyway.
- mehh 9y agoWat?
- laumars 9y agoIf your REST APIs do updates or retrieve sensitive information then odds are you'll have some kind of authentication method, possibly with session cookies or whitelisted IPs. Allowing sensitive APIs to be sent via GET means that you open yourself up to a couple of easy vectors of attack. eg a malicious webpage with a <img src="http://example.com"> http://example.com"> tag using the API end point as the src URI. This means the target person opening the page will send the API request as themselves, using their IP and cookies. Granted the API wont return an image so the "image" will fail to render but that doesn't matter as the API will still execute successfully. However if your APIs only accept POST requests then you mitigate this particularly attack. It's pretty common advice to recommend any APIs that require user authentication to be sent via POST. In fact it's one of the first things pen testers will check for and you'd also fail PCI DSS vulnerability scans for exposing APIs via GET as well. Disclaimer: I've works on multiple projects that have been pen tested, been audited by the UK Gambling Commission and/or had to adhere to PCI Data Security Standards.
- iamphilrae 9y agoI just had this exact 'problem' with an API I'm building. I just ended up creating both routes which accessed the same internal function to return the same results - no duplication of code necessary. Personally I think this is a good resolve as it answers both use cases depending on the accesssors context.
- iamphilrae 9y agoTo add, my endpoints were: /accounts/{id}/users And /users/account/{id} Both return the users attached to a particular account.
- ruiseal 9y agoI think it depends on what makes sense for your problem domain. Think about what kind of HTTP methods and the associated data with each and decide accordingly. Nesting of resources in a REST API can become problematic, for these reasons, so another option would be to get rid of the nesting and use query parameters to filter based on whatever criteria you want. This is the motivation for PostgREST [1] where the author views the shortcomings of nested API resources as similar to those of hierarchical databases. GraphQL solves this similarly, it also has a richer query language, but it's missing some of the benefits of REST like caching, etc. [1]. https://postgrest.com/en/v4.1/intro.html https://postgrest.com/en/v4.1/intro.html
- mkhattab 9y agoI believe '/courses' and 'student/1234/courses' mean two different things. The former implies a list of courses and the later implies an association between a student and a course. POSTing to '/courses' creates a new course. However POSTing to a 'student/1234/courses' creates a relationship/association between a student and a course. So, it's two different things IMO and not a duplication of logic.
- 3pt14159 9y agoThis isn't true. Or at least not necessarily true. If you're referring to the JSON API spec you're conflating related and relationship links. The former is strictly for GETs (GET students/5/courses) and the later is for controlling the relationship itself (PATCH students/5/relationship/courses). See here for more information: http://jsonapi.org/format/upcoming/#crud-updating-to-many-relationships http://jsonapi.org/format/upcoming/#crud-updating-to-many-re...
- 3pt14159 9y agoThis isn't true. Or at least not necessarily true. If you're referring to the JSON API spec you're conflating related and relationship links. The former is strictly for GETs (GET students/5/courses) and the later is for controlling the relationship itself (PATCH students/5/relationship/courses). See here for more information: http://jsonapi.org/format/upcoming/#crud-updating-to-many-relationships http://jsonapi.org/format/upcoming/#crud-updating-to-many-re...
- 3pt14159 9y agoI follow JSON API v1.1, mostly anyway, see [1]. I not only create both paths, I also specifically create `relationships` links to control the relationship itself. That way, I have a restful way of, say, making a signed article anonymous. DELETE articles/2/relationships/author not that this doesn't delete the author just the relationship itself. Your worry about the duplication of code is well founded, but slightly off. For what are called "related" links (articles/4/author) we only ever issue GETs. There are many reasons for this and you've started to catch onto a few of them. This means a _lot_ of routes (over 300 right now), but with smart abstractions it's not so bad. I've been thinking of doing a weird fork of Rails based on how productive I've become. Basically I want to follow Rails but I want to override a lot of their decisions that don't fit JSON API's needs. Maybe one day. [1] With a minor addition that I find helpful: I add an `also` link in the relationship body. GET articles/5/author would have `also` set to `users/45`. In this manner I can easily get a reference to the related resource and I make it explicit that the resource isn't dependant on it's relationship continuing to exist with the parent resource.