REST convention for function based services - rest

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

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

Different endpoints to get a resource in a API 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"
}]
}

Getting child products via rest/V1/configurable-products/(sku)/children

On Magento 2.3.1 we need to get all products + child products from a certain SKU via the REST API. My problem is that child products are only loaded if I use the storefront url in the API call - Not if I use the main install url.
Why is the response from the main store domain empty?
To get main configurable products:
https://(main-store-domain)/rest/V1/products?fields=items[sku,name]&searchCriteria[pageSize]=1000
and
https://(store-view-domain)/rest/V1/products?fields=items[sku,name]&searchCriteria[pageSize]=1000
Both of the above works fine.
To get child variants:
https://(main-store-domain)/rest/V1/configurable-products/(sku)/children (Gives an empty response)
https://(store-view-domain)/rest/V1/configurable-products/(sku)/children (Gives me the child products)
I would expect both /rest/V1/configurable-products/(sku)/children to give me the list of child products

URL design restful api

Lets assume that i want to build a restful api which should add items to a shoppingcart. I think the most straight forward way would be like this:
POST /shoppingcarts/{shoppingCartId}/items - to generate an itemId
PUT /shoppingcarts/{shoppingCartId}/items/{itemId}
Now it is possible that a shoppingcart does not exist when i want to add an item to it. There is also a requirement that the client must not create a shopping cart. If the client adds an item and a shoppingcart does not exist then it should be created.
Now i would design the api like this:
POST /shoppingcartitems - to generate a shoppingcartItem
PUT /shoppingcartitems/{shoppingcartItems}
Does this makes sense at all? Or is there another way to do this.
A follow up question would be that when an item is created the complete shopping cart should be returned. Returning the complete shopping cart when creating an item seems wrong since it is a different resource. I would probably just add a hypermedia link into the body of the created item which points to the shopping cart. Would that be also correct?
If I understand it correctly, there are two resources to manage, ShoppingCarts and Items.
If the business logic is to create a shoppingCart before adding items to it...
Then, the following design should work.
A) To create a shopping cart
POST: /shoppingcarts/
return: {shoppingcart-id}
B) Then create/add item to the shopping cart
POST: /shoppingcarts/{shoppingcart-id}/
BODY: {data about the item}
return: {item-id}
Or can be more specific with "items" in the url.
POST: /shoppingcarts/{shoppingcart-id}/items/
BODY: {data about the item}
return: {item-id}
C) To get all items in the shopping cart
GET: /shoppingcarts/{shoppingcart-id}/items/
return: {data for all items}
D) To get a specific item in the shopping cart
GET: /shoppingcarts/{shoppingcart-id}/items/{item-id}/
return: {data for the item}
E) To delete an item from the shopping cart.
DELETE: /shoppingcarts/{shoppingcart-id}/items/{item-id}/
Also PUT is to modify an existing resource not to create a new resource.
Like if need to update the quantity for the item that already exists, will do the following.
PUT: /shoppingcarts/{shoppingcart-id}/items/{item-id}/
BODY: {quantity: 2, {the rest of the item info} }
OR you can use PATCH to just update the quantity.
PATCH: /shoppingcarts/{shoppingcart-id}/items/{item-id}/
BODY: {quantity: 2}
Hope it helps!

Container URLs with querystring, is it RESTFul?

Suppose I have a container which is a resource containing a set of resources, for example:
http://www.example.com/persons
returns all persons
Now if I have want that it doesn't return me all persons but only a subset meeting a certain criteria like http://www.example.com/persons?age=18
is such a URL adhears to the RESTFul convention ?