In RESTful websites, each resource should be identified by an URI. But how should I handle what are called "weak entities" in relational databases, aka, ressources that only make sense when related to another resource? Should these have specific URIs pointing to them too?
To give an example: Say I have a website for showing events going on in a city. Each event can have comments posted by users.
An event is a resource, with corresponding URI (/events/:id).
But should each comment have an URI, too? Like /events/:eventid/comments/:commentid ? Comments only make sense when they're associated with the corresponding event, so having a page just to represent one message seems weird/unnecessary. I only want the comments to appear on the page of the event.
I guess the /events/:eventid/comments/:commentid URI could be used for a DELETE request, but what should it return to a GET request?
An event is a resource, with corresponding URI (/events/:id).
But should each comment have an URI, too? Like /events/:eventid/comments/:commentid ?
If comment is a resource, it must have an identifier, but it doesn't mean that you have to support all operations for such resource. The server can return a response with the 405 status code if a method is not supported by the target resource:
6.5.5. 405 Method Not Allowed
The 405 (Method Not Allowed) status code indicates that the method received in the request-line is known by the origin server but not supported by the target resource. [...]
I guess the /events/:eventid/comments/:commentid URI could be used for a DELETE request, but what should it return to a GET request?
Return a representation of the comment with the given identifier.
In RESTful websites, each resource should be identified by an URI. But how should I handle what are called "weak entities" in relational databases, aka, ressources that only make sense when related to another resource? Should these have specific URIs pointing to them too?
It depends. An important thing to recognize is that resources and entities are not one to one. You are allowed to have many resources (web pages) that include information from the same entity.
Jim Webber described the distinction this way
The web is not your domain, it's a document management system. All the HTTP verbs apply to the document management domain. URIs do NOT map onto domain objects - that violates encapsulation.
Domain Driven Design for Restful Systems
I guess the /events/:eventid/comments/:commentid URI could be used for a DELETE request, but what should it return to a GET request?
As noted by Cassio, 405 Method Not Allowed is the correct status code to use if the client erroneously sends a request with an unsupported method. OPTIONS is the appropriate mechanism for informing a client of which methods are currently supported by a resource.
You could also have it respond by redirecting the client to the /events/:eventId resource; it might even make sense to take advantage of URI Fragment support, and redirect the client to /events/:eventid#:commentid - allowing the client to use its own fragment discovery to identify the specific comment within the representation of the event.
Or, if there are useful integrations that you want to support, you could simply have this resource return a representation that exposes the integrations.
It really depends on how the client wants to work with the domain. Would an app want to get a list of all the comments for an event? Are users allowed to update their commments? Or are they anonymous comments?
If you plan to only ever use the same page to display the backend information of events and comments, then you prolly don't need a separate comments api. If you want to open the dataset to app vendors (perhaps you might want to develop an app in future) a comments api would be handy. i.e. get all comments for an event.
Related
In my API, resources can be write-protected. Trying to DELETE such a resource will return a 409 (Conflict) response.
For users that are allowed to change the protected state of a resource, I want to introduce the option to delete protected resources with one request. How should this option be passed?
Possible solutions:
Request body -- should not be used with delete requests
Query parameter -- changes the URI, so technically refers to a different resource
Custom header -- generally discouraged
Standard header -- none apply
Two requests -- not atomic, things could happen in-between (eg another user modifying the resource)
Alternative endpoint -- not restful?
Related Questions
In REST API, can DELETE methods have parameters?
Answer says yes to query parameters, but asks about deleting a subset of a collection
REST, HTTP DELETE and parameters
Asks about a confirmation flag, answers say it should be handled in UI instead of API
Also says it violates the uniform interface principle, but doesn't explain why and how
Also argues that using query parameters would violate URI principle
RESTful Alternatives to DELETE Request Body
Accepted answer says to use the body, but many commenters report technical issues
Query parameters are suggested as alternative, concern about URI principle is raised
Is an entity body allowed for an HTTP DELETE request?
Says not to use the request body, even if technically allowed
Whats the best way to design DELETE for a restful resource
Says to use query parameters, but again in a subset context
For users that are allowed to change the protected state of a resource, I want to introduce the option to delete protected resources with one request. How should this option be passed?
If the meaning of the request message is consistent with HTTP DELETE, then you should probably just use HTTP DELETE, rather than trying to invent a dialect that allows you to discriminate between DELETE and no-no-I-really-mean-it-DELETE.
Are your message semantics consistent with HTTP DELETE? You may want to consider this observation in RFC 9110
Relatively few resources allow the DELETE method -- its primary use is for remote authoring environments, where the user has some direction regarding its effect.
DELETE is the method token we send to a web server when we want that server to stop sharing representations of a resource. It's semantics are rooted in the transfer of documents over a network domain.
On the other hand, if the message isn't consistent with HTTP DELETE, then you should consider using HTTP POST.
POST serves many useful purposes in HTTP, including the general purpose of “this action isn’t worth standardizing.” -- Fielding, 2009
Here's a way of thinking about the distinction: our goal in creating a "REST API" is to create a facade that disguises our domain service as an HTTP-aware document store.
If what the client is really doing is marking a document as hidden in the store; and as a side effect of that we may make a bunch of changes in our domain service, then DELETE is appropriate.
On the other hand, if what the client is really doing is sending information to our domain service, and as a side effect some documents are going to be hidden, then POST is appropriate.
Lets assume we have a resource on an URL like so: foo.com/api/bar
And lets say that a user might be allowed to GET that resource, but not allowed to POST to that resource.
I can easily solve that by specifying different permissions per verb.
But how should the client know on beforhand if it is allowed to perform the POST?
Lets say we have a "save" button on a page, that should not be enabled if the user lacks the rights to do a POST.
I know about HATEOAS/Hypermedia constraint, and that I can pass a list of links for different actions together with the resource.
But AFAIK, that doesn't carry information on what verbs to use, only URL's for different actions.
Are there other variations where the verb is included?
Are there other approaches if you don't want to clutter the resource with all sorts of metadata?
This has been asked a lot on the HAL discuss forums https://groups.google.com/forum/#!forum/hal-discuss
The fact that verbs aren't returned is a decision of the hypermedia format you're using, which i'm guessing is HAL (or maybe collection+json). Some formats DO include verb information.
HAL actually allows you to include custom fields on your link objects if you wish, but i would discourage this because any standard client won't know how to interpret this.
But also i've found the verb to be worthless in the end.
First off in human 2 machine the user is going to read documentation. HAL has all of it's links dereference (via CURIE's as they are currently naemd) to human readable documentation that should describe the effects of requesting that link with different parameters, verbs, headers, etc.
Next off is that for your Application to be truly RESTful you should respond to all verbs...you might just not respond that the verb was OK. For an HTTP based app returning a 405 is VERY appropriate. Returning a 404 is not! A 500 would be worse!. Your 405 should include what methods are available for the requested resource.
Next in the case of machine 2 machine (and a bit of h2m) your application when accessed via HTTP (i try to avoid http in my answers as RESTful applications aren't necessarily HTTP..although i'd say 101% of them are) should use the OPTIONS method (http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html) against the resource URL in order to get a description of what's possible.
Here's where i see a lot of people getting tripped up, what should the response of OPTIONS be? well what people forget is content type negotiation! The requester should say what format for option information they expect. Accept: some-machine-language/xml or application/language+json. Some RFC or standards define these content types and your API can identify what formats it supports. I would suggest you include support for text/html so that you can return human readable documentation as well about what verbs are supported. This covers the h2m scenario nicely.
The same content type negotiation can be useful when returning info about a method not being supported. The server can send a content-type that the client can understand that describes semantically what methods are allowed.
The final thing i like to point out is that methods imply client intent. i want to PUT this resource or DELETE that resource. The server should accept requests and return responses indicated what state transitions occurred because of that request. Thus it's a little silly to have the API identify possible intents of the client with every request. The client knows what it wants to do, it should try, and if it can't then it should deal with that.
HTTP Verbs are pure transport protocol verbs. Those might not be the right verbs to do application functions, precisely because of the issues you mentioned in the question. So let us see if we can approach this differently without using http verbs. Doing http verbs to do appliction actions might limit us tommorrow as we might have need to move from http to another protocol.
LEt us take an example to illustrate. Let us say we are talking about Update Delete application using HATEOAS. So in this case, if the there are two products, represented by the URL www.abc.com/product/001 and www.abc.com/product/002. In a true HATEOAS situation, If the response of the two products product/001 and product/002 has to be looked at show the client screens.
So if the response to product/001 has a response product/001/delete,product/001/change and product/002 has the response product/002/Change then the client will show delete for only product/001 and change for the other two products.
So in response to your question. By appropriately identifying actions with product now it is possible to do role based actions.
I hope i have answered your question.
I am new to RESTful APIs and everywhere I read that REST APIs "must be hypertext-driven". I have googled a lot but haven't found a concrete explanation of the concept. So:
In practical terms, what does it mean that REST APIs should be 'hypertext-driven'?.
When I say hypertext, I mean the simultaneous presentation of information and controls such that the information becomes the affordance through which the user (or automaton) obtains choices and selects action. Roy T. Fielding - http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven
It is about one of the fundamental constraints of REST architectural style - Hypermedia As The Engine Of Application State (HATEOAS). It means that in any given moment, client, based on hypermedia in representation of current resource, must have all the information he needs to decide where to transit next(change its Application State). That hypermedia controls in hypertext connect resources to each other, and describe their capabilities in machine-readable ways. A REST client just needs to know one thing in order to communicate with REST server - understanding of hypermedia. Opposite, in a service-oriented architecture(SOA), clients and servers interact through a fixed interface shared through documentation or an interface description language (IDL).
HATEOAS decouples client and server so that they can be developed separately.
For example,
If you make an initial call to a rest service to add a customer using some URL /customers/ then you will get a response back (consider the customer is successfully added),
HTTP/1.1 201 Created
Location: http://www.myREST/customers/<uuid>/
Now the client who made the call to add customer knows how to find the corresponding customer from the link returned as a response header.
You may ask how does client know that he can make POST to /customer/. By different means - hypermedia controls, DSL specific formats and profiles.
REST mean that api follow correct use for HTTP Verbs, Status code, etc. HTTP protocol, has verbs like: GET, POST, PUT, OPTIONS and DELETE. In a rest api, each verb is map to specific action on resource. For example:
POST is allways create a new instance of resource; GET is get the resource (or a list), DELETE is allways remove resource associated; PUT is modify/update a exist resource .....
Plus, you should use the status code for indicate response : 201 to create, 200 to modify, etc.
You can take more information on http://restinpractice.com/book/ (Jim Weber book)
I'm reasonably sure I understand the server-side of HATEOAS design - returning state URL's in the response - but I'm slightly confused about how to design a client to accept these.
For instance, we access a resource at //somehost.com/resource/1 - this provides us with the resource data and links. We'll assume POST to //somehost.com/resource is returned, indicating a 'new' action. Now I understand posting some data to that url creates a new resource, and provides a response, but where does the form to post that data reside? I've seen implementations where //somehost.com/resource/1/new provides a form which POSTS to /resource, but that URL itself contains a verb, and seems to violate REST.
I think my confusion lies in that I'm implementing a RESTful API and a client to consume it, within the same application.
Is there some sort of best-practice for this sort of thing?
I've seen implementations where //somehost.com/resource/1/new provides a form which POSTS to /resource, but that URL itself contains a verb, and seems to violate REST.
This is incorrect. A URI containing a verb does not, in itself, violate any REST constraint. It is only when that URI represents an action that this becomes a violation. If you can perform a GET request on the URL and receive some meaningful resource (such as a "create new resource" form), then that is perfectly RESTful, and good practice.
My own API is exactly as you describe: /{collection}/new returns a form. /new is just shorthand for a hypothetical /new-resource-creation-form and still represents a noun, and only supports GET requests (HEAD, OPTIONS and TRACE not withstanding).
What HATEOAS prohibits is the user agent being required to know, that in order to create a new resource, it must add /new to the name of the collection.
Basically, if you implement your API as (X)HTML, and can surf it in a browser and perform all actions (AJAX may be required for non-POST form submissions until HTML and browsers catch up with HTTP), then it complies with the hypermedia constraint of REST.
EDIT promoted from comments:
As long as the response negates any need for a priori knowledge, it conforms to the hypermedia constraint. If the client claims to understand HTML, and you send back a response containing a link to an external stylesheet or javascript (no matter where that is hosted) which the client needs to be able to render the page correctly, then it is reasonable to say that the constraint is met. The client should know how to handle all media types it claims to support. A normal human web browser is the perfect example of a client with no out-of-band knowledge about any one HTTP service (web site).
Just to say it explicitly, a web site is a kind of HTTP service. Web browsers do not treat different web sites differently. In order to search for products on Amazon, you load the Amazon service endpoint at http://amazon.com/ and follow links or fill out forms provided in that response. In order to search for products on eBay, you load the eBay service endpoint at http://ebay.com/ and do the same.
Browsers don't know in advance that for searching eBay you must do this, but for searching Amazon you have to do that. Browsers are ignorant. Clients for other HTTP services should be ignorant too.
Yes, you could provide a URI that returns a form for resource creation. Conceivably the form could be used for dynamic discovery of the elements needed to construct a new resource (but you'd want to decide how practical that would really be in a machine-to-machine environment).
Unless there is a requirement that somehow the API has an exact browser-surfable equivalent, the documentation of the media type will describe what elements are needed.
Remember that documentation of media types and the allowed HTTP verbs for a resource is not contrary to RESTful principles. Look at the SunCloud API for an example.
Indeed, according to your example, POST'ing to
//somehost.com/resource
to create a new resource is more standard than first returning a form
//somehost.com/resource/1/new
and THEN POST'ing to
//somehost.com/resource
anyway.
Is it appropriate to perform actions with REST, other than simple create (POST), read (GET), update (PUT), and delete (DELETE)? I'm kind of new to the whole RESTful theology, so bear with me, but how should I accomplish the following:
I have a web service that needs to talk to another web service. Web service A needs to "reserve" an object on Web service B. This object has a timeout of validity, but can be deleted immediately if need be. It's essentially a glorified permissions system which requires web services to reserve a space on web service B before taking any actions.
My initial thought was to 1. enable authentication of some sort, 2. in the serverside response to a GET call, reserve the space and return the result, and 3. provide immediate "unreservation" of the object via a DELETE call. Is this still being RESTful?
Yes, it's OK to perform actions with rest. What matters is that these actions should be guided by the representations you exchange.
If you think about the way the web works (via a browser), you do this all the time: you get an HTML form that lets you choose a number of actions you can perform. Then, you submit the form (typically via POST) and the action is performed.
It's good to be able to use DELETE via a programmatic client (which is something that non-AJAX requests in browsers wouldn't support), but the overall approach of a RESTful system should be very similar to what you find for websites (i.e. the focus should be on the representations: the equivalent of web pages in your system).
GET shouldn't have side effects, so don't use GET to make the reservation itself, use something like POST instead.
No - unlikely to be restful
From your description ...
2. in the serverside response to a GET call, reserve the space and return the result
GETs should be idempotent. For this reason alone, your service is unlikely to be restful because the state of the system after the first GET is different.
You really need to consider that a Reservation is a resource and should be created with a POST to a reservations container which will return the URI of the new resource in the Location header of the HTTP response. This UrI can be used by Get to return the resource and updated with a PUT
Post should be used to extend an existing resource and Put for replacing the state of a resource. In your case, consider the Post to be updating a list of Reservations and returning the URI of the new resource (not just the I'd). Put can be used for changing the state associated with the resource identified by the UR
You're on the right track, but your reservation of the object should be with a PUT; you're PUTting a reservation on the object, i.e. changing the underlying object.
PUT is the right verb here, since you know what resource you're modifying, and it should be idempotent for multiple requests.