REST and showing URIs that need user input - rest

I have a REST Service that works with Models. So once a user has navigated to a model I allow two endpoints /ModelRootItems and also /Item.
The /Item endpoint requires an ID of an item within the model eg: /Item/1234.
When a user gets to a model I return the following URIs:
/Model/My_Model/ModelRootItems
/Model/My_Model/Item/{ItemID}
But I feel that I should not expose the /Item URI as it is not complete without an ID. Users are able to see that the /Item endpoint exists via my help page.
So is it right/wrong to show this endpoint in the list of URIs?

I don't think there are right/wrong choices in this case. However, I'd suggest you use
/Model/My_Model/Items
(notice the plural form Items) to return a list containing all the items of that Model and
/Model/My_Model/Items/{ItemID}
to return the single Item referenced by the ID.
Please note that this is just a convention, as I already said, there is no right/wrong choice in this case, especially if you use REST's HATEOAS principle with opaque URIs.

Related

How to instruct REST API to include additional data for given resource

I've implemented a GET request as followed:
https://api.com/invoices?filter[status]=paid&include=client
Current situation: Fetch invoices with status 'paid' & include client data for each invoice record
Now, I'd like to instruct my API to include additional data for each invoice record. This additional data is not really related to the invoice. (for example a log record of the last login of the client)
Desired: What are the best practices here? Which query param should I add according to industry standards, to instruct the request to include this additional data, as I wouldn't like to execute a query per invoice to fetch the last login for the client
How to instruct REST API to include additional data for given resource
Spelling check; as far as REST is concerned, you aren't asking for a given resource with additional data, you are asking for a different resource. There's no particular reason that this new resource needs an identifier related to the existing one.
What are the best practices here?
Think about how you would do it with a web site.
The URI would be created by presenting a form to the user, with input elements to allow the client to specify the values in the query string. In other words, the form is playing the role of a URI Template.
So to give the consumer additional control, you would include a new input control in the form - it might be a free text field, or it might be something like a list control which enumerates specific possible values.
Which query param should I add according to industry standards
There are a couple possibilities.
You could review the list of IANA Link Relations, to see if there is a close match. Technically, link relations aren't query parameters. But what this list does is match spellings with semantics, which is what you really want: is there a common understanding of foobar that you can leverage for your own needs.
Another possibility is to look in resources like schema.org, which again has lots of interesting mappings between spelling and semantics.
I happen to know off the top of my head that the EventStore API uses embed with different values to allow the client to specify that it wants to access resources with richer information; but to the best of my knowledge that choice was arbitrary, not based on any real "industry standard".
how about this,
example :
// your code here
$result; // your variable that will send by your API
$user = User::all(); // your additional query to be included to your response API
// additional data example all user data
$result['user'] = $user;

Is it considered RESTful if single POST requests create multiple resources?

We have customers API that takes {customer-name, customer-mobile, customer-email} and creates customer in the database.
We also have order API that takes {productId, customer-name, customer-mobile, customer-email}.
The code for order API:
First creates customer based on {name,mobile,email} passed in the order API and return back customerId.
The {productId, customerId} further gets saved in the database in the order table.
Is this restful practice that one API is internally first creating some other resource?
Please note that its an over simplified example where API expects only one type of product in the order API.
It's fine for a single POST call to result in multiple resources being created. It's not generally the best idea but there are use cases where it makes sense - example cases might include (usual legal disclaimer... not limited to...)
the POST method is to the parent resource of all the created resources. So, a POST /accounts call might result in an /accounts/<accountId> resource being created but also an /accounts/<accountId>/tweets resource. In this instance, the /accounts/<accountId> parent is the 'actual' resource being created.
the POST method might create multiple resources representing multiple ways in which the resource may interact with other parts of the system. So, a POST /accounts response might create resources under /accounts/<accountId> and /users/<accountId> (because an account is-a user and user id are a super set of account ids, for arguments sake). However, the client really only gets told about the one under the '/accounts' path (via the Location header). The other created resource is basically a side-effect.
The key point, really, is that the POST method returns a single Location header - representing the 'primary' resource created - and that subsequent 'GET's on that URI are capable of locating any the other resources via links.
If you find yourself in a situation where creating multiple resources via a single POST request results in you having to return different values for the Location header, then something's wrong with your resource breakdown. It should be clear that a 'POST' will always create one particular type of resource, a URI to being returned in the header. Other resources might be created as side-effects.

How to design api to retrieve one resource by non-primary key in RESTful style?

Original, we have a api GET /users/:id to retrieve a user by its primary key.
Now we need a new api to retrieve a user by its email.
GET /users?email=xx#xx.com seems like to get a collection.
GET /users/byEmail/:email includes a non-noun word byEmail.
Is there any other choice?
Both approaches you have suggested are valid on their own, but I probably wouldn't do both as it's best to stick with one URI per resource. Another common way to do this is:
/users/id/:id
or
/users/email/:email
I should point out that the choice of query params vs url params or /name/:value vs /:value is not what make a service "RESTful". Put another way, having "pretty" or "readable" URLs does not automatically mean your service is RESTful.
One of the key points of REST is resource identification through a URI i.e. a particular URI will always point to a particular resource. In the case of email, this could probably change (user may want to change their email address) so this url no longer identifies this user at all times.
A more RESTful approach would be to make explicit that this is really a search and not an identifier, and have a URI like this:
/search/users/email/:email
This is more RESTful because this URI always identifies the same resource, namely the search results for this email address. Note that the resource in this case is the search results, not the user resource itself.
I like the convention that URIs with / at the end of the path are the collections. So GET /users?email=xx#xx.com returns an item and GET /users/?email=xx#xx.com returns a collection with a single item. But ofc. you don't have to use this convention.
Another options are using /users/:email if you can solve the routing on the server, or /users-by-email/:email or /users/email-:email, etc... It is not important which URI structure you choose as long as your REST API meets with the HATEOAS constraint.

RESTful URI to select "My" items

I want to expose my Item resource in these ways:
GET /Item (to show all Items)
GET /Item/401 (to show only the Item with key value 401)
So far so good. Now to request only the Items that belong to Me, I can think of these possible URIs constructions:
GET /Item/Mine
GET /MyItem
GET /Item/owner=42 (where my ID is 42)
I don't like the last one because it simplifies my client programming to rely on existing authentication to figure out "My" ID. I happen to be coding on ASP.NET WebAPI, but I'm really asking about the principle and design, not the implementation.
My question: Which of the three ways to represent "My" Items is most consistent with the RESTful design concept? Is it even legitimate to ask for "My" Items as such?
If users should not be able to see items that aren't "theirs", then this is an authorization issue. Just use GET /Item, and have your authorization module strip out the items that aren't theirs.
If users can see all items, and you just want to grab the items that belong to a particular user, then you should be parameterizing the call to GET /Item. Something like GET /Item/?owner=42. In this case, the user isn't limited to asking for their items .. they can ask for the items of any owner. That buys them flexibility without costing you anything.
If you have a /User resource, you could also add an endpoint /User/{id}/Item, which
returns the same collection as /Item/?owner=
And this isn't germane, but I find that plural collections (/Items, /Users) read a lot better than singulars. YMMV.
I would use GET /Items to get all itmes.
And GET /Items?owner=42.
GET /Item/Mine is not consistent since it contradicts your way of identifying the resource ie, GET /Item/401.
GET /MyItem seems seems unnecessary since the resources you are looking for can be retrieved using the other REST url paths.

REST URI definition

I can't get comfortable with defining 'good REST' URIs. The scenario is an existing site with products for sale. You can view data in a number of views, drilling down a hierarchy, but basically cat1/cat/ products, or cat 2/cat3/products or any combination of categories 1 to 4. The other products view is based on a search.
How do you form the URI's?
products/??????
Having designed a site that follows the principles of the REST architecture, my advice is to base your decision on your URI structure solely on your server design, that is how your server will parse an incoming URI and deliver the corresponding resource.
One principle of REST design (as I see it) is that your users/clients will NEVER have to form a URL to find a resource, they will instead read some hypertext (i.e. HTML) which describes resources, identify what they want, and get the appropriate link from the hypertext (for example, in HTML, the href attribute of the tag holds the URL, which could just as well be a random string of characters.
Again, in my opinion, if your application requires that a user/client be able to perform searches for arbitrarily named categories, it's probably not suitable to have a RESTfully designed interface.
You can use use a query string in your URI:
/products?categories=german,adult,foo,bar
In order to avoid multiple URIs you could enforce some logic like alphabetical ordering of categories on the server side so a request to the above URI would actually redirect via a 301 Moved Permanently response to:
/products?categories=adult,bar,foo,german
For that above query part pattern to work in browsers you will have to use JavaScript to generate the query from any html forms - you could, alternatively, do it like this if you wanted to avoid that particular problem:
/products?cat1=adult&cat2=bar&cat3=foo&cat4=german
Yes - the problem here is that you don't have a unique ID for the resource because:
products/cat1/cat4
Is actually the same page as
products/cat4/cat1
(Presumably a view of everything tagged with cat1 and cat4, or all matches from cat1 and cat4)
If your categories where organised into a hierarchy you would know that "cat6" is a child of "cat1", for example.
So your two options would be
1) Enforce a natural order for the categories
or
2) Have two different URI's essentially pointing to the same resource (with a 301 permanant redirect to your preferred resource).