There are 2 models: Entity and Subentity. Entity can have many connected Subentities (one:many relation).
There is a method on server that returns new Subentity (let's call it GetEmptySubentity). Point is, when you want to create new Subentity, you press a button, and model comes from server with some fields pre-filled. Some of those Subentity pre-filled values depend on according Entity, so I need to pass an Entity id in this request.
So should the correct url to get the empty Subentity be like /Entity/{id}/Subentity/empty? Or I am getting something wrong?
Yes you are. According to the uniform interface / hateoas constraint you should send hyperlinks to your REST clients and they should use the API by following those hyperlinks. In order to do this you need a hypermedia format, for example HTML, ATOM+XML, HAL+JSON, LD+JSON & Hydra, etc... (use google). So by HTML the result should contain a HTML form with input fields having default values, etc... You should add semantics to that for with RDFa and so by processing the HTML your REST client will know, that the link is about creating a new resource. Ofc it is easier to parse the other hypermedia formats. By them you can use the same concept with RDF (by JSON-LD or ATOM for example), or you can use link relations with vendor specific MIME types (by HAL or ATOM for example), or your custom solution which describes those input fields. So you usually get the necessary information with the hyperlink, and you don't have to send another request to get the default values.
If you want to make things complicated, then you can send a request for the default values to the entity itself in order to send the values of properties, and not to send a form with input fields. Optionally you can send a request which returns the entire link, for example GET /Entity/{id}/SubEntity/offset=0&count=0 can return an empty array of subentities and the form for creation. You can use additional query or path parameters if that form is really big, and you don't want to send it with every response related to the SubEntity collection. The URL specification says only that the path should contain the hierarchical part and the query should contain the non-hierarchical part of the URL.
Btw. REST is just a delivery method, you don't have to map it to your database entities. The REST resource and URL structure can be completely different from your database, since you can use any type of data storage mechanisms with REST, even the file system...
Related
When creating an UPDATE endpoint to change a resource, the ID should be set in the path variable and also in the request body.
Before updating a resource, I check if the resource exists, and if not, I would respond with 404 Not Found.
Now I ask myself which of the two information I should use and if I should check if both values are the same.
For example:
PUT /users/42
// request body
{
"id": 42,
"username": "user42"
}
You should PUT only the properties you can change into the request body and omit read-only properties. So you should check the id in the URI, because it is the only one that should exist in the message.
It is convenient to accept the "id" field in the payload. But you have to be sure it is the same as the path parameter. I solve this problem by setting the id field to the value of the path parameter (be sure to explain that in the Swagger of the API). In pseudo-code :
idParam = request.getPathParam("id");
object = request.getPayload();
object.id = idParam;
So all these calls are equivalent :
PUT /users/42 + {"id":"42", ...}
PUT /users/42 + {"id":"41", ...}
PUT /users/42 + {"id":null, ...}
PUT /users/42 + {...}
Why do you need the id both in URL and in the body? because now you have to validate that they are both the same or ignore one in any case. If it is a requirement for some reason, than pick which one is the one that is definitive and ignore the other one. If you don't have to have this strange duplication, than I'd say pass it in the body only
If you take a closer look at how HTTP works you might notice that the URI used to send a request to is also used as key for caching results. Any non-safe operation performed on that URI, such as POST, PUT, PATCH, will lead to (intermediary) caches automatically invalidating any stored responses for that URI. As such, if you use an other URI than the actual resource URI you are actually bypassing that feature and risk getting served outdated state from caches. As caching is one of the few constraints REST has simply skipping all caching via certain directives isn't ideal in first place.
In regards to including the ID of the resource or domain entity in the URI and/or in the payload: A common mistake in designing so-called REST APIs is that the domain object is mapped in a 1:1 manner onto a resource. We had a customer once who went through a merger and in a result they ended up with the same products being addressed by multiple IDs. In order to reduce the data in their DB they at one point tried to consolidate their data and continue. But they had to support still the old URIs they exposed for their products. In the end they realized that exposing the product ID via the URI wasn't ideal in their situation as it lead to plenty of downstream changes that affected their customers. As such, a recommendation here is to use UUIDs that don't give the target resource any semantic meaning and don't ever change. If the product ID in the back changes it doesn't affect the exposed URI at all. Sure, you might need a further table/collection to map from the product to the actual resource URI but you in the end designed your system with the eventuality of change which it now is more likely to coop with.
I've read so many times that the product ID shouldn't be part of the resource as it is already present in the URI. First, the whole URI is a unique identifier of that resource and not only a part of it. Next as mentioned above, IMO the product ID shouldn't be part of the URI in first place but it should be part of the resources' state. After all, the product ID is part of the products properties and therefore should be included there accordingly. As such, the media type exposed should contain all the necessities that a client is able to identify the product ID off the payload. The media type the resource's state is exchange with should also provide means to include the ID if you want to perform an update. I.e. if you take HTML as example, here you get served a HTML form by the server which basically teaches you where to send the request to, which HTTP operation to use, which media-type to marshal the request with and the actual properties of the resource, including the ones you are not meant to change. HTML does this i.e. via hidden input fields. Other form-based media types, such as HAL forms, JsonForms or Ion, might provide other mechanisms though.
So, to sum my post up:
Don't map the product ID onto URIs. Use a mapping from product ID to UUIDs instead
Use form-based media-types that support clients in creating requests. These media types should allow to include unmodifiable properties, such as hidden input fields and the like
How do you decide where do parameters go?
Suppose the API is for an object, which has an ID, a few fields and each request may or may not have a token. There has to be GET, PUT, POST and DELETE requests for the object.
As a rule, you want all of the parameters necessary to identify a resource to be directly encoded into the URI somewhere. That allows you to bookmark the URI for re-use later, and to share that bookmark with another person/process.
Example:
Building a REST API: How to decide which params go to Headers, Body, URL or query?
All of the context you need to GET this resource is right here. You can click it, save it, send it off in an email, and it is still useful, of itself.
So where in the URI does information go?
If the information is only needed by the client once the representation has been downloaded, then you might consider encoding it into the fragment.
The fragment identifier component of a URI allows indirect identification of a secondary resource by reference to a primary resource and additional identifying information.
On the web, fragments were useful because they allowed you to call upon the user agent to focus at a particular element in a representation. The fragment is not sent over the network, but only used on the client side. Think Data Transfer Object - one big cacheable document (so we don't need a lot of round trips) with lots of URI that point to specific information within it.
Other parameters can be encoded into path segments or the query string. The machines don't care (20 years ago, this was somewhat less true - we would sometimes have to work around caches that didn't handle the query part of a URI correctly).
URI with parameters configured via application/x-www-form-urlencoded query strings were convenient on the web because HTML had form support for creating those identifiers on the client.
These days, we can use URI templates to describe how to compute a new URI, which gives you more options.
Relative resolution gives us a general purpose mechanism for computing a new URI from a given reference identifier. Think dot-references with symbolic links. That mechanism is primarily based on navigating the hierarchical part of the URI, which is to say that path.
The machines don't care of the hierarchy of resources and the hierarchy of identifiers are parallel
# Here's an identifier for a collection
/collection
# Here's an identifier for a member of this collection
/collection/member
# Here's an identifier for a collection
/2c957fb6-ac92-4fdb-a086-02292c3b7c7c
# Here's an identifier for a member of this collection
/41d36a69-d10c-4503-8e5e-3b2d64e9c3a6
All of these samples are fine, as far as the machines are concerned; but human beings tend to have an easier time working with the top set.
Headers are metadata that belongs to the domain of "transporting documents over a network".
The body is the document itself - it is the message that is being transported over the network (the http request and the headers are, in a sense, the envelope that carries the message). Yes, this sometimes means that information that is in the message also gets copied into the headers, or copied via the template into the target-uri.
Consider a need to create a GET endpoint for fetching Member details using either of 4 options (It's common in legacy application with RPC calls)
Get member by ID
Get member by SSN
Get member by a combination of Phone and LastName (both must be passed)
What's a recommended strategy to live the REST spirit and yet provide this flexibility?
Some options I could think of are:
Parameters Based
/user/{ID}
/user?ssn=?
/user?phone=?&lname=?
Separate Endpoints
/user/{ID}
/user/SSN/{SSNID}
/user/{lname}/{phone}
RPC for custom
/user/{ID}
/user/findBySSN/
/user/findbycontact/
REST doesn't care what spelling you use for your identifiers.
For example, think about how you would do this on the web. You would provide forms, one for each set of search criteria. The consumer would choose which form to use, and submit the form, without ever knowing what the URI is.
In the case of HTML forms, there are specific processing rules for describing how the form information will be copied into the URI. The form takes on the aspect of a URI Template.
A URI Template provides both a structural description of a URI space and, when variable values are provided, machine-readable instructions on how to construct a URI corresponding to those values.
But there aren't any rules saying that restrict the server from providing a URI template that directs the client to copy the variable values into path segments rather than into the query string.
In other words, in REST, the server retains control of its own URI space.
You might sometimes prefer to use path segments because of their hierarchical nature, which may be convenient if you want the client to use relative resolution of relative references in your representations.
REST ≠ pretty URLs. The two are orthogonal.
Your question is about the latter, I feel.
Whilst the other answers have been good, if you want your API to work with HTML forms, go with query parameters on the collection /user resource for all fields, even for ID (assuming a human is typing these in based on information they are getting from sheets of paper on their desk, etc.)
If your server is able to produce links to each record, always produce canonical links such as /users/{id}, don't duplicate data under different URLs.
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;
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).