Different endpoints to get a resource in a API REST - rest

I have a REST API with a GET endpoint to retrieve a product based on the id. Now I need to retrieve a product based on another attribute and I don't know if I have to use the same endpoint and handle the multiple cases there or write different endpoints, one for each case.
Thanks!

Let's say you have
GET /product/{id}
And you want to be able to lookup products by some other attribute. If the attribute uniquely identifies a product you could do:
GET /product?someOtherAttribute=foo
return
302 FOUND
Location: /product/5
If you want to avoid the roundtrip you could return the contents of product directly, but as you pointed out that may require additional logic in your controller.
If the attribute does not uniquely identify a product, I'd recommend a paginated collection response:
GET /products?someOtherAttribute=foo
return
200 OK
{
products: [{
url: "/product/5"
}, {
url: "/product/6"
}]
}

Related

In OpenAPI 3.0, how do I create a link from a list of entities to a single entity?

In most OpenAPI 3.0 documentation (like the official one), links are introduced with a combination of a POST endpoint to create an entity returning an ID linking to a GET endpoint to fetch that entity by that same returned ID:
POST /users -> UserID
GET /users/{UserID} -> User
In Schemathesis context, this would assume an empty data storage and simulate a create+fetch scenario. I would like to test my GET endpoints on a pre-warmed data storage and implement a "fetch a list, then fetch each entity from the list by ID" scenario:
GET /users -> List[User] -> List[UserID]
GET /users/{UserID} -> User for each entry in the list
For this to work, I need an OpenAPI link from the list GET endpoint to the entity GET endpoint, however I can't seem to find either an example or a confirmation that this is indeed possible.
Can I and if so how can I create such a link in OpenAPI 3.0?
OpenAPI links are defined using JSON Pointers. JSON Pointers are quite limited - they can only point to a specific field within a JSON Structure (such as "the first element of this array", or the entire array) and don't support wildcard expressions (such as "any/each element of this array").
This means, for example, that if you have the GET /users endpoint that returns
[
{
"id": "29d590d1-02b2-4aa1-9ce5-98202cc9a619",
"username": "nikolai",
...
},
{
"id": "58091b14-eb06-47ee-b896-50cebdda20ef",
"username": "helen",
...
},
...
]
you can define a link like $response.body#/0/id to indicate that the id of the first user in the list can be used as a parameter to another endpoint. But there's no way for a link to reference an arbitrary/each user from the list.
You can check these discussions in the OpenAPI Specification repository for more details:
Link for array element
Variables/Parameters in Links

Is it RESTful if we fetch multiple resources using path variable over query parameter?

Is it RESTful to have HTTP GET /employees/1,2,3,4,5? Or should this be modeled as HTTP GET /employees?id=1,2,3,4,5
This question is more about URI design than REST.
A URI is intended to identify a particular resource in the server. While /employees identify a collection of employees, a URI like /employees/{id} should identify an employee with the given id in that collection. The slash expresses hierarchy.
If you want to get multiple resources from that collection (in fact, perform a query in that collection), it makes more sense to use a query parameter. Both approaches are valid:
GET /employees?id=1,2,3,4,5
GET /employees?id=1&id=2&id=3&id=4&id=5
I had a simiar requirement to print all the data starting an index and ending with an index, I used query params as below. You can try this..
You can use..
../../employees?start=1&end=5
#GET
#Produces(MediaType.TEXT_PLAIN)
public String getInjectResources(#QueryParam("start") String start,
#QueryParam("end") String end){
String queryParams = "start: "+start+" end: "+end;
// Your logic here..
}

RESTful API - different types of children resources

I'm dealing with tree-structred resources. Every item resource has children. Each child type may be content resource or subject resource - which is determind by the type_id. (There could be more children types in the future).
What URI should be used for creating a new child for an item?
POST /api/items/<item_id>/children
(deliver the type_id via the JSON)
OR:
POST /api/items/<item_id>/children/contents
POST /api/items/<item_id>/children/subjects
OR: redirection according to the type_id to:
POST /api/contents
POST /api/subjects
And then using the GUID of the new resource for creating the hierarchy connection.
Thanks!
If your children have an attribute named type which can be subjects or contents, you can treat that as any other attribute, e.g. a gender that can be male or female.
Ideally, you would create a new child with
POST /api/items/<item_id>/children
{
"some_value": 50
"type": "subject",
}
or
POST /api/items/<item_id>/children
{
"some_value": 134
"type": "content",
}
No need to make a confusing endpoint for a simple attribute. If you'd do this for the type attribute, you might as well do it for all the other attributes as well, leading to a great many more endpoints pointing to basically the same resources, that is not something you want.
Later you can fetch them by type, for example getting all subjects would be
GET /api/items/<item_id>/children?type=subject

REST convention for function based services

The typical REST endpoints service looks like this for an entity.
GET /products (list)
GET /products/:id (detail of a specific product)
POST /products (insert)
PUT /products/:id (update)
DELETE /products/:id (delete)
but if I've a requirement to return some custom result, for example
SELECT MAX(lastModified) FROM product
How would you form a REST request (method + URL) based on above or similar custom results?
If you are only interested in the "lastModifed" product from your list of products (i.e. the product with MAX(lastModified)) then:
GET /products/lastModified

RESTFul way to reference resource with unique fields

One of the requirements for our REST interface is that each resource be identifiable by unique fields (aside from the primary identifier). The reason for this is that we want to be able to handle bulk importing data - in which case the client can't know the system generated primary identifiers.
This means we have to be able to reference our resources by unique fields. Using a primary key our read requests look like this:
GET example.com/rest/customers/1
and to get orders related to that customer
GET example.com/rest/customers/1/orders
Now, lets assume two fields in customer identify it uniquely, name ("foo") and businessId ("bar"). Given that, I came up with the following URI to get the orders for this customer:
GET example.com/someotherpath/customers/foo,bar/orders
But I don't like that I have a different path to identify that this is a resource being accessed via unique fields. How would you structure the above query in a RESTful way using unique fields instead of the primary key?
Further, an order looks like this:
{
<SNIP>
"orderId" : "42"
"_links": {
"customer": {
"href" : "rest/customers/1"
"key": [ "foo", "bar" ]
}
},
}
Any issues with allowing client to interchangeably specify href OR key when communicating with the interface?
For the first bit, I just wouldn't do it. If a customer has a unique id (and they should), I wouldn't allow end users to specify N other fields that happen to also uniquely identify the customer. It's messy for the user (which field goes first?) and also messy for you on the back end.
For the second bit, the issue is: what happens when they specify both? Which takes precedence? Are they going to remember? Do you want to have to support both? It's generally a good idea to only allow one way to do any particular thing if you can get away with it.