Is my approach to book a room in a conference hall:
PUT: api/v1/rooms/book/1
GET: api/v1/rooms/1
POST: api/v1/rooms
fits REST architecture?
With your approach, you define the "book" as a resource - which is fine in restful perspective.
But - the http method will be better to be a "POST" for this situation, as you create a new instance of the "book" resource (this is more restfuly in case you consider "book" as a resource, which you are).
and it basically means that the POST method should include the room_id in the request body rather than book/1
Rooms resource:
GET: api/v1/rooms/books/ - All the booking
POST: api/v1/rooms/books - book new (room_id in body) - there's a better restful approach in the next resource:
Book resource
GET: api/v1/rooms/<room_id>/books/ - Get room room_id books
POST: api/v1/rooms/1/book book new (book id in url resource, more restful than rhe rooms resource example)
a book resource
PUT api/v1/rooms/<room_id>/books/<book_id> - Update book information
GET api/v1/rooms/<room_id>/books/<book_id> - Retrieve book information
As you clearly asked for whether your design fits the REST architecture:
Actually the form of the URI is not of relevance in a REST architecture. Clients will use link relation strings to lookup a URI dynamically. I.e. if a client wants to progress to the next page it will look for a URI annotated with next (see registered link relations at IANA). In case there is no fitting link-relation yet present at IANA's registry you can either attempt to register one or fall back to an approach outlined by Web linking extension, which uses a URI that does not necessarily need to target an actual resource but just defines the relation within an own namespace. Technically, each relation builds up a triple (subject, predicate, object), similar to an ontology, where the subject is always the current resource and object always the target resource and the predicate being the link relation name or verb in that triple. A URI can further have multiple link-relations assigned, i.e. create-form https://acme.org/rel/book-room where the first create-form link relation indicates that the resource will provide a form to create a new resource and the second one, the Web linking extension one, will indicate to clients that support this kind of relation that a room can be booked using the underlying URI. This whole indirection allows a server to change its URI scheme anytime it wants to and clients will still be able to make further requests.
Please note though that resources in a REST architecture never have types that are significant to clients. This is similar to the Web we interact on a daily basis. Even though we visit different HTML pages that represent car models, shopping products and what not, the content returned by the server is still a HTML page containing data that could also be expressed in other representation formats. HTML after all just defines which tags are valid within the scope of the HTML document (syntax) received as well what each of these tags expresses (semantics). Through content-type negotiation both client and server can and should agree on a representation format both understand and can operate on.
In case a server expects some client input an approach very similar to traditional Web surfing done by humans can and should be used. Humans usually interact with HTML based Web-Forms. Here, the form teaches a client about the properties a resource supports, the target URI to send the request to, the HTTP operation to use as well as (most often implicitly given) the media type to use for marshalling the payload to before transmitting the request. This way clients learn new features a server has for a resource automatically.
The intent of a REST architecture is besides the decoupling of clients from servers also the freedom of evolution on the server side so that new features can be introduced without breaking any clients. As HTTP and URI define a standard interface that is widely supported by languages and frameworks, the core focus needs to be put on the actual media-type exchanged between client and servers. This is the coupling part between both of them. The overall question here should not be which media-type to support but how many different ones as with each one you support you just increase the likelihood of your application being able to interact with peers in that architecture.
So your actual question whether your URI design fits a REST architecture can't be answered actually as, as mentioned throughout this post, REST is more than meaningful URIs or which HTTP operation you perform on a URI. From a true REST architecture standpoint your URIs are fine as far as they don't violate with the URI specification. In general, one of the best advice to give on designing peers in a REST architecture is to model the whole interaction as if you'd design a browser-based Web interaction and than transfer the same concepts onto a more general application layer using link support through HAL JSON or JSON Hyper-Schema or form-support through HAL forms or ION in case you prefer exchanging JSON payloads.
Related
My understanding of REST is simply that a resource needs some means of self-describing itself. My understanding is that this isn't specifically tied to any one protocol (i.e. HTTP) and that there are theoretically numerous ways of achieving this. This is based on an answer to a SO question here: SOAP vs REST (differences) (and unlike the terrible answer to this question: Are Relay and Graphql RESTful?)
Since a GraphQL API is self-describing via introspection, doesn't that mean that GraphQL is RESTful by default since a client can use introspection to figure out how to query it?
While GraphQL is often mentioned as the replacement for REST, both tackle different problems actually.
REST, to start with, is not a protocol but just a style, which, if applied correctly and fully, just decouples clients from servers. A server following the REST principals will therefore provide the client with any information needed to take further steps. A client initially starts without any a-priori knowledge and learns on the fly through issuing requests and processing responses. HATEOAS describes the interaction model a REST architectue should be build upon. It thereby states that a link should be used to request new information which drives its internal flow. On utilizing similar representation to Web forms (HTML) a server can teach a client on needed inputs. Through the affordance of the respective elements a client knows, without any need for external documentation, what to do. I.e. It might find a couple of options to chose one or multiple options from, enter or update some freetext or push some buttons. In HTML forms usually trigger a POST request and send the entered data as application/x-www-form-urlenceded to the server though the form element itself may define something different.
While REST is protocol agnostic, meaning it can be build up ontop of many protocols, HTTP is probably the most prominent one. A common sample for a RESTful client is the Web browser we are all to familiar with. It will start by invoking either a bookmarked URI or invoke one entered in the address bar and progress from there on.
HTTP doesn't specify the representation the request or response has to be sent in but leaves that to clients and servers negotiating them. This helps in decoupling as both client and servers can rely on the common interface (HTTP) and only bind strongly onto the known media types used to exchange data in. A peer not being able to process a document in a certain representation (due to the lack of the respective mime type support) will indicate his other peer via a respective HTTP status code that it does not understand, and therefore can't serve, the requested media-type format. The media type, which is just a human readable documentation of the syntax and the semantics of the data payload, is therefore the most important part in a REST architecture. Even Fielding claimed:
A REST API should spend almost all of its descriptive effort in defining the media type(s) used for representing resources and driving application state, or in defining extended relation names and/or hypertext-enabled mark-up for existing standard media types. Any effort spent describing what methods to use on what URIs of interest should be entirely defined within the scope of the processing rules for a media type (and, in most cases, already defined by existing media types). [Failure here implies that out-of-band information is driving interaction instead of hypertext.]
A media type teaches a peer how to parse and interpret the received payload and to actually make sense out of it, though plenty of people still confuse REST for a JSON based HTTP API with over-engineered URIs they put to much effort in to give the URI some kind of logical sense when actually neither client nor server will interpret it anyway as they will probably use the link relation name given for the URI.
GraphQL on the other hand is a basically just a query language which gives the client the power to request specific fields and elements it wants to retrieve from the server. It is, loosely speaking, some kind of SQL for the Web, or as Fielding termed it just a Remote Data Access (RDA). It therefore has to have some knowledge of the available data beforehand which couples clients somehow to the server. If the server will rename some of the fields, the client might not be able to retrieve that kind of information further, though I'm not a GraphQL expert.
As stated above, REST is often confused for a JSON based HTTP API that allows to perform queries on directly mapped DB entries/entities. Keep in mind that REST doesn't prohibit this, though its focus is on the decoupling of peers not the retrieval aspect of some Web exposed database entries. As Jim Webber pointed out in a great talk back in 2011 in REST you don't simply expose database tables, you create a domain application protocol which clients will follow along like in a text-based computer game or in a typical Webshop system on the internet.
Especially the linked introspection documentation of GraphQL reminds me of reflection in Java, which couples to the actual class model available. If something along the datamodel changes, how does the GraphQL interaction behave? Is it able to change and adapt? Is a client built for one API able to work with an other API out of the box? All these are basically requirements for a true RESTful client. It basically has to adept to changes in future as the server is free to evolve anytime. It further shouldn't assume certain endpoints returning certain types but use content type negotiation to request a representation it can work upon.
These should give you enough insights to determine for yourself whether GraphQL can be RESTful or not. In my opinion it isn't, but my insights into GraphQL are rather limited, TBH.
Because graphql publishes Metadata about its types, it's entirely plausible (I think) to build a graphql client that could consume any graphql endpoint ...
SOAP did the exact same thing, though it was still an RPC protocol. A client could look up the ...?wsdl information at run-time and then generate a request according to the schema defined in the WSDL dynamically, though what usually happened was that some pre-generated stub-classes were generated based on the WSDL data that got compiled into a specific client. A client dynamically generating a request still needed a routine that defines what message-type to create and what data the message required as input.
While SOAP could potentially define multiple endpoints within a WSDL, in most cases only one was defined though. This endpoint usually only operates on POST requests even when later on (SOAP 1.2) GET would have been possible also.
According to Fielding's thesis
REST uses a resource identifier to identify the particular resource involved in an interaction between components.
, what would be the resource identifier in GraphQL? GraphQL's documentation states that
... In contrast, GraphQL's conceptual model is an entity graph. As a result, entities in GraphQL are not identified by URLs. Instead, a GraphQL server operates on a single URL/endpoint, usually /graphql, and all GraphQL requests for a given service should be directed at this endpoint.
Similar to SOAP, all the request are targeted towards a single endpoint. This has some impact if you consider caching, which is a further constraint REST implies. How are responses cacheable if the URI is the key used to store the response in the cache?
While all of the aggregation stuff and the flexibility may be nice from a consumer perspective, they are, probably, not in line with the constraints of REST, though Fielding himself claimed that REST is not applicable in all situations and that designers should select a style that fits their needs as not every style is the "silver bullet" to each problem. Even Mike Amundsen stated that GraphQL violates at least 3 constraints imposed by the REST architecture, even though GraphQL seems to have changed the default retrieval method from POST to GET since.
Usually, if you aim for long-living APIs that should be free to evolve in future and that has to deal with lots of clients, especially ones not under your direct control, this is when REST starts to shine. Fielding admits that most developers have problems when thinking long-term. For a single frontend-to-backend system or for a tailor-made client interacting with the own API, REST is not the architecture one should probably follow.
Last but not least, in a later tweet Fielding stated
There is no such thing as a REST endpoint. There are resources. A countably infinite set of resources bound only by restrictions on URL length. A client can POST to a REST service to create a resource that is a GraphQL query, and then GET that resource with all benefits of REST…
which I interpret as, don't focus to much on justifying whether GraphQL is REST or not, but think about how you can integrate its benefits into the overall design.
I hope this question will be accepted by stack overflow and not be tagged "opinion based". At least I try...
I talked with a supplier that have to develop for us a web application and The agreement was to use a RESTful interface to access to services provided by my infrastructure.
The REST interface will be developed by my team and their team will develop the UI Interface. The API is in an advanced state of development and it is used by the main application my company is using, so I have to extend it to accomodate this new webapp.
He sent me a draft document to interface their client applications telling me to develop services like this:
http://1.2.3.4:8080/getGPSPositions
telling me:
1) the web frontend will use POST to ask its requests on the above URL
2) the frontend will send objects serialized using JSON with a format s like this (simplified)
{
serviceID: <number>
fromDate: <date>
toDate: <date>
customSQLWhere: <string>
customSQLOrderBy: <string>
}
and response like this:
{
gps_points:
{
#some data object
}
}
This is no REST to me, but JSON+HTTP+RPC with some embedded SQL code, that can be used by an attacker to do some SQL injection...
I think that the correct resource for the above example (about gpsPositions) is:
http://1.2.3.4:8080/gPSPositions?fromDate=...&toDate=...
using HTTP/GET and not HTTP/POST (using fro CRUD operations GET,DELETE,PUT and POST).
I would like to know the technical implications that this kind of approach can have on my project. the API will be exposed on the Internet and in the future it should be used by more supplier for different kind of applications. I also fear to develop an API with two different styles (RPC and REST) should be difficult to read and understand and this will be a problem in the future.
Thank you for your suggestions.
Actually, neither the OP nor his supplier have a correct understanding of REST, IMO.
REST is an architectural style which basically describes how client and servers should interact with each others in order to decouple the former from the latter. The decoupling is achieved by using a backing protocol (HTTP in your case) as transport layer and utilizing the available operations to exchange data. HTTP, which at its core is actually just a protocol to manage resources on a remote location, therefore defines the semantics of each operation, not REST. The decoupling is furthermore achieved by adhering to the rules outlined by the backing transport protocol and by generating new (or utilizing existing) media types both parties can use. Instead of clients coupling to the server API, both couple to intermediary media types instead. This is why Fielding stressed that REST APIs should spend almost all of their descriptive efforts in defining the media types used for representing resources.
Media types per se are just textual descriptions of the syntax and the semantic to expect on receiving data annotated to be of that kind. It is thus a knowledge base for peers on how to process the data and give the data some useful meaning. Clients and servers should further use content negotiation to agree on a common media type both understand. I.e. a client could send a server a list of media types the client knows of and the server will pick the one that is probably most suitable of for the available data or send an unsupported media type failure back to the client to indicate that none of the requested media types is known by the server.
It is furthermore important that the server provides clients with all of the information the client could need to take further actions. The client shouldn't parse meaning out of provided URIs but use the relation name instead and look up the semantics of the relation name within the exchanged media type, i.e. or rely on common standards like next, prev, first, last and self in a collection. This gives the server the freedom to change URIs (and thus move resources around freely) without breaking clients.
One common error of so called RESTful APIs (and clients using those) is, that data is exchanged as application/json or application/hal+json or the like media type only and clients expect resources to be of a certain type (typed resources), which already couple clients to the API. First, application/json or application/xml is a bad media-type in general as it does not hint the users on what content the document might contain. As the example code contains geo-location data probably application/vnd.geo+json would be more appropriate in that particular case.
As REST's focus is on resources, it is questionable IMO if geo-location data make up for a good resource. I at least consider them more of some kind of property of an entity that I'd express as resource. As the location seems to change over time this might be some kind of vehicle information (car, bus, truck, plane, ship, ...) or the like. The proposed response is in itself not very self-descriptive. The client therefore has to have some build in knowledge that somethin like gps_points in a JSON payload contain GPS data probably as time series for someting.
If the server decicdes to return data in a slightly different representation the client risks to break easily this way. On relying on common media types this risk is almost erased unless both parties adhere to the media types specification.
As your actual post more or less questions if POST requests are feasible instead of GET request on retrieving data:
Accoroding to HTTP the client expresses his intent by using one of the available operations defined within the spec. POST is actually an optional operation that should be used if none of the other operations fits the needs. It is kind of a swiss-army knife that can be misued easily. Using it for other operations is not wrong per se. The spec here states:
The POST method requests that the target resource process the representation enclosed in the request according to the resource's own specific semantics.
On retrieving data, GET is the preferable operation in case the request does not modify any state on the server or requires to extensive data in via a body (as plenty of HTTP clients limit the length of URIs that can be invoked).
The actual implication of accepting data retrieval via POST is, that this becomes part of your API and you have to support it further on. If you decide to later on "fix" this issue you risk of breaking clients that used this kind of communicating with your API. Some legacy systems might force you though to use such constructs. We have some RPC like Web services where we have to provide services to a wide variety of clients. Some of these are SOAP clients in an old SAP version that gets misued in order to send data to our services. As there is actually no build-in support for HTTP in that ABAP version (as far as I'm told) we have to accept such retrieval requests per POST as well. As I changed our API once in order to accept only GET data retrieval I broke plenty of legacy clients that way unintentionally (even once that could retrieve via GET actually) as the developers just used the first sample in the documentation, which was still POST at that time. Long story short, I had to roll back the changes and support both kinds of queries from now on.
I've heard about the conception RESTFul for a long time but I always can't understand it clearly.
I've read the links below:
What are RESTful web services?
What exactly is RESTful programming?
As my understanding, RESTFul means that the URL shouldn't contain any verb, meaning that an URL represents an unique resource. And also, the method GET shouldn't modify any resource and we should use POST to do so.
But I still have a question.
For example, if we want to search a user by his name, we can design the URL like this:
www.example.com/user?name=test
Or like this:
www.example.com/user/name/test
Can you tell me which one is RESTFul?
When you are using rest - you are accessing resources through URI's and you can set actions on these resources through the HTTP request types.
There are different parameters that you can pass through REST request , there can be resource identifiers (That are usually passed through the URI - in your case the www.example.com/user/name/test is more restfull) or things like filters when you want to search, for example www.example.com/user/?age=....
In this post you can find more about best practices in passing parameters in rest:
REST API Best practices: Where to put parameters?
REST, to start with, is not a protocol but just an architectural style that when followed correctly decouples clients from server APIs and thus make them tolerant to changes done on the serverside. It should therefore be regarded as a design approach for distributed systems.
The difference between a protocol and an architectural style is simply that the former one defines a rule set a server or client has to follow. It should be defined as precise as possible to reduce ambiguity and thus reduce the likelihood of incompatible implementations by different vendors. The latter one just contains suggestions how to design the overall application and/or message flow and outlining the benefits one gains by adhering to the design.
By that definition, REST is a generalization of the interaction style used for browsing Web content. A Web browser is able to make use of multiple protocols such as HTTP, FTP, SMTP, IMAP, ... and different flavors of it while remaining independant of any server specific implementation though being capable of interacting with it as the communication is done according to the rules of the protocol used. REST does follow this approach by building up on the same protocols (most often just HTTP) which an application implementing the RESTful architeturce approach should adhere to as well to stay compatible with other users of that protocol.
Similar to a Web browser, which does not care whether the URI string contains any semantical structure, REST doesn't care how the URI is designed or if the resource is named after a verb either. Both will use the URI just to invoke a resource on the server providing the resource. A RESTful client should thus not expect a certain URI to return a certain type (= typed resources). Though how will a client know what an invoked URI will return? The keywords here are content-negotiation and media-types.
The format exchanged by both, Web browser and REST, is negotiated between client and server. While for typical Web browsers the representation is probably one of the HTML variants (i.e. XHTML, HTML 5, ...) it is not limited to it. Your browser is probably capable of processing other media types as well, i.e. pictures, videos, PDF, ... As REST is just a generalization of this idea it also should not limit itself to just XML or JSON.
Media types are thus some kind of guildlines of how to process and interpret data received in a representation format outlined by the media type. It should define the syntax and semantics of a received payload i.e. like text/html, which defines that a received representation will have a case-insensitive <html token (<xhtml in case of XHTML) near the beginning of the content and that fragment identifiers (# character in URIs) are according to URI semantics and that certain tags like A, IMG or others may define a name attribute which act as a target for anchors. It may also define a more thorough description of the syntax and how to interpret it like in case of text/vcard (vCard) (or one of its variants like application/vcard+json (jCard) or application/vcard+xml (xCard)).
As media types are one of the most important parts of the RESTful design, most effort has to be put into its creation. A client that can't deduct the next possible actions from the media type needs some out-of-band information which often is hardcoded into the client and thus couples it tightly to the API itself. If the API will change in future, the chances that the client will stop working once the changes are applied on the server are fairly high (depending on the changes).
I hope I could shed some light on the idea behind REST and that the design of URI is not of relevance to a true RESTful client/API as the client might deduct what to do with that URI based on some relation name returned for the URI and the media-type which might state that a relation name such as order can be invoked to trigger a new order with the API rather than having the client to analyze something like http://some.server.com/api/order/product/1234 or http:/some.server.com/ajfajd/fj/afja.
Further information and reasons why RESTful APIs should follow the design closely can be found in Roy Fielding famous blog post which explains some of the constraints an API should adhere to if it follows the RESTful approach.
REST resource is a noun, no notion of behavior should be in the uri, we use verbs to indicate action we are doing. Basically there are only two types of resources: Instance and Collections. So good practise is to use plurals in the uri: users instead of user:
www.example.com/users GET - fetch collection of all users
www.example.com/users/1 GET - fetch instance of a concrete user
www.example.com/users POST - create of a new user
etc.
REST is not a strict standard (but a list of 6 constraints) says nothing about how search feature should be implemented. But definetely your first option /users?name=test seems preferable for me: tt is straightforward and this is a huge benefit.
As alternative you may want to investigate OData protocol - it is a standard to make queryable apis. OData-like solution would be:
/users?$filter=name eq 'test'
Also Facebook APIs is a good source for inspiration.
Hope this helps
In the explanation of the differences between web services or (Web) APIs there seems to be agreement that REST results in a less coupled architecture.
For example:
https://datatracker.ietf.org/doc/html/draft-li-sdnrg-design-restapi-02 mentions that REST is suited for lowly coupled systems.
https://www.upwork.com/hiring/development/soap-vs-rest-comparing-two-apis/ states that SOAP is too highly coupled
What are the arguments for considering it less or lightly coupled?
In a systems where clients aren't coupled to a specifiy service API, clients will in general be more failure tolerant and thus robust besides being usable for multiple RESTful APIs in general. They will adapt to changes done on the server side while a tightly coupled client will fail to process further requests.
In REST API must be hypertext-driven Fielding explained some of the constraints a RESTful architecture has and what could happend if an API fails to respect these rules.
As clients use links to interact with some remote server, a client has to have some knowledge on what a link is and what actions it can perform on it. This knowledge is in general defined by HTTP (or any other transport protocol) and URI specifications which are often built into the client by relying on certain frameworks or middleware. As links are a major part in REST and clients have to learn respective endpoints somehow Fielding referred to this in his blog post as:
... allow servers to instruct clients on how to construct appropriate URIs, such as is done in HTML forms and URI templates, by defining those instructions within media types and link relations.
though you see plenty of so-called "REST" services that do not support clients on this by not returning URIs at all or not keeping the semantics in the relation but put them into the URI. I.e. you will often see something like URIs like http://some.server.com/api/v1/users/1234 which may give humans a clue of its purpose though if this "knowledge" is ported to a client, it might brake it easily if the server decides (or is instructed by someone) to change anything in the structure. If the server now moves the resource to i.e. http://some.server.com/api/v1/employees/1234 the client wont be able to retrieve data of the user/employee any longer and thus break.
Instead the server should instruct the client with the needed information. It can add some redirect logic which upon invoking the former URI informs the client that the resource can now be found at the new location. The response from the server itself should name such a URI so a client can refer to a resource endpoint via the name instead of analyzing the URI. In HTML this can be achived like this: Sam Sample. Instead of the client analyzing the URI for semantical structures, which also often leads to typed resources, it simply uses what is given by the server and grasp the sense of the URI via the relational name user in the sample.
As HTTP (or any other transmission protocol used) allows to send almost any data between client and server, media types are used by server and clients in order to agree upon a data representation format both sides are able to understand and know how to process. The media type is therefore some kind of knowledge base of what to do with certain data. It can describe the syntactical structure of a document, the necessary elements to expect and the semantics each field has.
According to Fielding
a REST API should spend almost all of its descriptive effort in defining the media type(s) used for representing resources and driving application state, or in defining extended relation names and/or hypertext-enabled mark-up for existing standard media types. Any effort spent describing what methods to use on what URIs of interest should be entirely defined within the scope of the processing rules for a media type
If you, however, take a close look at plenty of questions here at StackOverflow most messages are exchanged in plain JSON which does not convey any semantics about the actual data received nor does it hint the client on possible actions that can be performed on this data. HAL and similar media types at least provide some clue on resources and links a client can use in order to process further actions.
As the media type defines a client or server on how to process certain data, it might contain an indication that a link with a relation name like user references a user resource further data of that users can be retrieved from. If the URI of the resource is changed a RESTful client will still be able to process its task as it can deduct from the media type that the user information for a user can be retrieved via the relation name user. Where this URI is actually pointing at isn't of much relevance as the client will only invoke it to retrieve further data from.
As the question also targeted SOAP it is important to know that the SOAP API is very different to REST by nature. The tight coupling is defined via the WSDL contract which defines the server endpoint as well as the operations available to invoke as well as the parameter needed and response types to expect. If the server is adding or (re)moving certain parameters after a client implemented that contract that client will fail from sending further requests and hence needs to be updated before it can continue to work.
In this very simple scenario of letting the server move arround some resources it hopefully becomes clear that a client's knowledge is kept in media types and its state it is aquiring through interacting with the services rather than having it implemented in the code itself (like in SOAP or any propriatary Web-API client). The client is therefore not coupled to the API itself but to the media types which can be added dynamically.
In terms of good REST API design, is it a good idea to return id of the newly created resource? Say I have an API:
api/resource POST
I've seen some guru who has such API to return empty json and insert the URI into with Location header in response. I think returning
{ 'id': '1000' }
so that the caller can do something right away with it is better. Save one more round-trip to the server. What's the problem with this approach if any?
As requested I reposted my comment as an answer and added some more details to be worth an answer at all.
The common approach for creating new resources via HTTP POST method is to return a 201 Created status code. The response furthermore should therefore contain the current state of the resource as entity body and a location header pointing to the URI the resource can be found. Not doing so, may break some clients and prevent their correct interaction with the service. Clients here may be browsers, tailor made "languageOfYourChoice" applications or even other services.
In an ideal RESTful world, the client is only aware of one single URI to start with (like the entrance URI of the service, f.e. http://service.company.com/). The response of an invocation of that URI should return a document which can be understood by the client and contains further links the client can use if interested. This concept is similar to the big brother HTML and similar web resources used everyday by humans where links can be used to move from the start page to sub-pages or even external resources or other hyper-media resources. REST is just an abstraction and a generalization of the Web thing.
Although not part of the actual question and this is rather opinion based, there is an ongoing discussion among RESTful devolopers regarding the usefulness of common vs. specialized document types (mime types, ...). I think that there should be a standardized common REST-aware format for JSON, XML, ... Just plain application/json is not enough as this does not define how links and schemas have to be included. Even HAL is not descriptive enough (IMO) regarding executable actions on URIs and what document formats to expect on invoking those URIs and what arguments needed to be passed to the service.
Document formats (a.k.a media types) are one of the core concepts of Roy Fieldings acronym HATEOAS. Clients should not need any prior knowledge other than the entrance point and the media types understood by the clients (thus the previous paragraph). The possible actions are all described through following the HTTP protocol specification and knowing what the respective media types express.
Therefore, returning a URI instead of an ID has a couple of advantages:
URIs are per se unique, different vendors though may have identical IDs
Client needs no knowledge on how the server is creating those URIs, the server on the other hand can provide them almost for free. Returning a product ID of 1234 has almost infintly ways to be combined in an URI by the client - the client therefore needs special knowledge on how to create the URI so that the server is actually able to process the request correctly.
The server can move resources without the need of clients to change as clients (in an ideal RESTful world) would retrieve the URI of the resource within a further request' response. The client therefore needs only the semantical knowledge what the returned field acutally "means"