How to name RESTful endpoint that's described using two identifiers? - rest

When resource has a unique identifier it is retrieved:
/building/{building_id}
But what if "event" resource is described using building_id and floor_id parameters. How to name RESTful endpoint that is meant to retrieve present events?
To be precise, "event" resource has a unique identifier (id). Combination of building_id, floor_id ought to return present event in a particular location.

But what if "event" resource is described using building_id and floor_id parameters.
Is it? I recommend this:
If
GET /events/{id}
returns one event and
GET /events
returns all events, then
GET /events?building_id={building_id}&floor_id={floor_id}
returns the list of (possibly only one) event(s) at the combination of building_id and floor_id.
This looks like the often used filter-or-search-a-collection-resource-pattern.

Apart from the solution by Lutz, in case if you dont want them to be query parameters.
Assuming, from the name as it looks, floor_id is part of building_id , so if the event resource is defined as combination of both , it can be like
/event/{event_id}/building/{building_id}/floor/{floor_Id}

I'd start by trying to think what resource owns what. Obviously, buildings own floors (knock the building down, the floor is destroyed!) so that's a relationship that maps nicely to a sub-resource, but do events own buildings or do buildings/floors own events? No? Then we relate these by links. (A floor might have a current event concept as something it owns, but that's really a link to an event, not an event per se.)
/building/{building_id}
/building/{building_id}/floor/{floor_id}
/building/{building_id}/floor/{floor_id}/current-event --redirect--> some event
/event/{event_id}
The event probably should have hyperlinks to the building and floor which it involves. Going the other way, if there's no current event for a floor, fetching the …/current-event will result in a 404, and if there is an event, a 303 redirect will say which it is. (You might also want to make the record for the floor itself contain a true link to the event, as well as a convenience lookup sub-resource.)
A good RESTful application looks an awful lot like a densely linked website. Use the power of links and redirects!

Related

How to properly access children by filtering parents in a single REST API call

I'm rewriting an API to be more RESTful, but I'm struggling with a design issue. I'll explain the situation first and then my question.
SITUATION:
I have two sets resources users and items. Each user has a list of item, so the resource path would like something like this:
api/v1/users/{userId}/items
Also each user has an isPrimary property, but only one user can be primary at a time. This means that if I want to get the primary user you'd do something like this:
api/v1/users?isPrimary=true
This should return a single "primary" user.
I have client of my API that wants to get the items of the primary user, but can't make two API calls (one to get the primary user and the second to get the items of the user, using the userId). Instead the client would like to make a single API call.
QUESTION:
How should I got about designing an API that fetches the items of a single user in only one API call when all the client has is the isPrimary query parameter for the user?
MY THOUGHTS:
I think I have a some options:
Option 1) api/v1/users?isPrimary=true will return the list of items along with the user data.
I don't like this one, because I have other API clients that call api/v1/users or api/v1/users?isPrimary=true to only get and parse through user data NOT item data. A user can have thousands of items, so returning those items every time would be taxing on both the client and the service.
Option 2) api/v1/users/items?isPrimary=true
I also don't like this because it's ugly and not really RESTful since there is not {userId} in the path and isPrimary isn't a property of items.
Option 3) api/v1/users?isPrimary=true&isShowingItems=true
This is like the first one, but I use another query parameter to flag whether or not to show the items belonging to the user in the response. The problem is that the query parameter is misleading because there is no isShowingItems property associated with a user.
Any help that you all could provide will be greatly appreciated. Thanks in advance.
There's no real standard solution for this, and all of your solutions are in my mind valid. So my answer will be a bit subjective.
Have you looked at HAL for your API format? HAL has a standard way to embed data from one resources into another (using _embedded) and it sounds like a pretty valid use-case for this.
The server can decide whether to embed the items based on a number of criteria, but one cheap solution might be to just add a query parameter like ?embed=items
Even if you don't use HAL, conceptually you could still copy this behavior similarly. Or maybe you only use _embedded. At least it's re-using an existing idea over building something new.
Aside from that practical solution, there is nothing in un-RESTful about exposing data at multiple endpoints. So if you created a resource like:
/v1/primary-user-with-items
Then this might be ugly and inconsistent with the rest of your API, but not inherently
'not RESTful' (sorry for the double negative).
You could include a List<User.Fieldset> parameter called fieldsets, and then include things if they are specified in fieldsets. This has the benefit that you can reuse the pattern by adding fieldsets onto any object in your API that has fields you might wish to include.
api/v1/users?isPrimary=true&fieldsets=items

Handling IDs in RESTful CRUD APIs

I am designing a Create/Read/Update/Delete public web API endpoint, using RESTful patterns over HTTP with JSON payloads, and am wondering about a design issue that must be extremely common, yet I'm finding a hard time finding guidance for.
Let's focus only on the "Read" and "Update" part of the API. I am a bit confused about the current "proper" REST best practices when it comes to handling IDs. Here's what I mean:
"Reading" employees over HTTP GET returns one or more "widget" JSON object (for example, I have a way to retrieve all widgets that meet a certain criteria). Each widget object has an ID field which is a GUID.
I see several design options for the "Update widget" endpoint:
HTTP PUT to /api/widgets/{widget-id} of the entire widget object. The API will fail if the "ID" field in the object is present. (I don't like this approach because data from the "Read" endpoint cannot be round-tripped to the "Update" endpoint without modification)
HTTP PUT to /api/widgets/{widget-id} of the entire widget object. The API will ignore the "ID" field in the object, if present. (I think it's better than the above, but the ID supplied can be incorrect, and I think it's wrong to silently ignore bad data)
HTTP PUT to /api/widgets/{widget-id} of the entire widget object. The API will verify that the ID field in the object must match the ID in the URI, and will fail otherwise. (I think this is even better, but data is still duplicated between the URI and message body)
HTTP PUT to /api/widgets/{widget-id} of the entire widget object. The API will verify that the ID field in the object must be either absent or must match the ID in the URI, and will fail otherwise. (This is the approach I'm leaning towards)
HTTP PUT to /api/widgets of the entire widget object, including the ID field - i.e. ID of the object to update will come from the message body instead of the URI.
Same as #5 but with HTTP POST - perhaps with "Update" semantics if the ID is specified, and "Create" semantics if it isn't.
I can see various tradeoffs here. Option 6 seems particularly elegant to me, but not particularly "RESTful" and may be an unfamiliar pattern to the API's users. Most of the API design guideline documents I've seen seem to recommend the "PUT to /api/widgets/{widget-id}" approach but are silent on the #1/2/3/4 distinction above.
So what is the "RESTfully correct"/best-practies way to do this? (Something that would be most familiar and least confusing to developers using my public API endpoint). And are there any other design options (or design considerations) I'm not thinking of here?
You can have the ID exposed if its definitely mandatory. Another approach is that, you can have a unique field in your Entity. Without passing the ID, you can create a DTO which contains the Unique field too. In your case {widget-id} is unique and the id is as always an auto generated id of int. Use POST and that's the best approach in your case of public API's.
If in case you need multiple actions over widgets, create 4 different endpoints with "Widget" (example: site.com/widget) which defines get, post, put as well as delete as different methods. This means that a single API will function differently based on different methods that it is invoked with.

Add subcategories in a filtered API Restful resource

I'll give an example as the title might sound a bit confusing.
How to build a resource path for something like that:
GET /courses/?language=english&active=true/units
I want to filter the courses (not using an id as usually) and then get the units of this result. How would you do that? I guess using question marks between the path is not allowed.
That would depend a little on your DB schema of what is a "course" and a "unit". The whole point on using the RESTful way is to always build requests and urls resource-specific.
But let's say that one course has X units on it. Here's what i would do to make a RESTful path to that request:
Due to the path problem of filtering courses AND using the /unit suffix, it can be done by adding another query parameter that specifies what fields the request is supposed to return. Something like this:
GET /courses?language=english&active=true&fields=units
That would filter the courses, and then return only the 'units' field on the response. As i said, depending on your DB and models, if the units are not stored inside the courses, it would be a bad practice to get them by requesting a /courses path. In that case, first request the courses that match the desired filter, and then make another request to the /units context sending i.e the courses ID's as query parameters.

REST where should end point go?

Suppose there's USERS and ORDERS
for a specific user's order list
You could do
/user/3/order_list
/order/?user=3
Which one is prefered and why?
Optional parameters tend to be easier to put in the query string.
If you want to return a 404 error when the parameter value does not correspond to an existing resource then I would tend towards a path segment parameter. e.g. /customer/232 where 232 is not a valid customer id.
If however you want to return an empty list then when the parameter is not found then query string parameters. e.g. /contacts?name=dave
If a parameter affects an entire URI structure then use a path e.g. a language parameter /en/document/foo.txt versus /document/foo.txt?language=en
If unique identifiers to be in a path rather than a query parameter.
Path is friendly for search engine/browser history/ Navigation.
When I started to create an API, I was thinking about the same question.
Video from apigee. help me a lot.
In a nutshell when you decide to build an API, you should decide which entity is independent and which is only related to someone.
For example, if you have a specific endpoint for orders with create/update/delete operations, then it will be fine to use a second approach /order/?user=3.
In the other way, if orders have only one representation, depends on a user and they don't have any special interaction then you could first approach.
There is also nice article about best practice
The whole point of REST is resources. You should try and map them as closely as possible to the actual requests you're going to get. I'd definitely not call it order_list because that looks like an action (you're "listing" the orders, while GET should be enough to tell you that you're getting something)
So, first of all I think you should have /users instead of /user, Then consider it as a tree structure:
A seller (for lack of a better name) can have multiple users
A user can have multiple orders
An order can have multiple items
So, I'd go for something like:
The seller can see its users with yourdomain.com/my/users
The details of a single user can be seen with yourdomain.com/my/users/3
The orders of a single user can be seen with yourdomain.com/my/users/3/orders
The items of a single order can be seen with yourdomain.com/my/users/3/orders/5

Looking for RESTful approach to update multiple resources with the same field set

The task: I have multiple resources that need to be updated in one HTTP call.
The resource type, field and value to update are the same for all resources.
Example: have set of cars by their IDs, need to update "status" of all cars to "sold".
Classic RESTFul approach: use request URL something like
PUT /cars
with JSON body like
[{id:1,status:sold},{id:2,status:sold},...]
However this seems to be an overkill: too many times to put status:sold
Looking for a RESTful way (I mean the way that is as close to "standard" rest protocol as possible) to send status:sold just once for all cars along with the list of car IDs to update. This is what I would do:
PUT /cars
With JSON
{ids=[1,2,...],status:sold} but I am not sure if this is truly RESTful approach.
Any ideas?
Also as an added benefit: I would like to be able to avoid JSON for small number of cars by simply setting up a URL with parameters something like this:
PUT /cars?ids=1,2,3&status=sold
Is this RESTful enough?
An even simpler way would just be:
{sold:[1,2,...]}
There's no need to have multiple methods for larger or smaller numbers of requests - it wastes development time and has no noteable impact upon performance or bandwidth.
As far as it being RESTful goes, as long as it's easily decipherable by the recipient and contains all the information you need, then there's no problem with it.
As I understand it using put is not sufficient to write a single property of a resource. One idea is to simply expose the property as a resource itself:
Therefore: PUT /car/carId/status with body content 'Sold'.
Updating more than one car should result in multiple puts since a request should only target a single resource.
Another Idea is to expose a certain protocol where you build a 'batch' resource.
POST /daily-deals-report/ body content {"sold" : [1, 2, 3, 4, 5]}
Then the system can simply acknowledge the deals being made and update the cars status itself. This way you create a whole new point of view and enable a more REST like api then you actually intended.
Also you should think about exposing a resource listing all cars that are available and therefore are ready for being sold (therefore not sold, and not needing repairs or are not rent).
GET /cars/pricelist?city=* -> List of all cars ready to be sold including car id and price.
This way a car do not have a status regarding who is owning the car. A resource is usually independent of its owner (owner is aggregating cars not a composite of it).
Whenever you have difficulties to map an operation to a resource your model tend to be flawed by object oriented thinking. With resources many relations (parent property) and status properties tend to be misplaced since designing resources is even more abstract than thinking in services.
If you need to manipulate many similar objects you need to identify the business process that triggers those changes and expose this process by a single resource describing its input (just like the daily deals report).