I'm coming from the RPC world but currently investigating if using REST is a good idea for my project. As for as I understand from Wikipedia the basic idea of RESTful services is to provide access to collections and their individual elements.
In my case the server would be a measuring instrument. I must be able to start, stop, and pause the measurement routine, and read the data at any time.
Currently, I'm considering the following:
POST /measure (start measurement, this continues until stopped by the user)
PUT /measure pause=true/false (pause/unpause)
DELETE /measure (stop)
GET /measure (get measurement data)
However, I'm not sure if this fits the REST model, since I don't really work with collections or elements here.
My question: How would I access a singleton resource and do the start/stop requests to the server break the RESTful stateless constraint?
Not RESTful
No, your approach isn't RESTful, because if I understand the workflow, you would delete the resource to stop the measurement and then get the resource to read out the final result. But deleting a resource implies that there would be nothing left to GET.
The fact that your resource is a singleton isn't a problem at all. The problem lies in the way you're mapping verbs and state.
Your description is a bit abstract, so let's be a bit more concrete: let's assume that the instrument in question measures the angular velocity of a fly wheel in radians/sec. This instrument has some cost associated with measurement, so the client needs to be able to disable measurement for some periods of time as a cost-saving measure. If this is roughly analogous to your scenario, then the exposition below should be applicable to your scenario.
Verbs
Now, let's review your verbs.
GET returns a representation of a resource. So when you GET /measure, it should return some data that represents the current measurement.
PUT creates or updates a specific, named resource. The resource is named by its URL. So PUT /measure implies that you're updating the state of a resource called /measure, or creating that resource if it doesn't already exist. In your case, the instrument value is read-only: we can't write a radian/sec value to the instrument. But the paused/active state of the instrument is mutable, so PUT /measure should include a body that modifies the state of the instrument. You could use a lot of different representations here, but one simple approach would be a request body like active=true or active=false to indicate what thew instrument's new state should be.
POST is similar to PUT, except that the client does not specify the name of the resource that should be created or updated. In a different API, for example, the client might POST /articles to create a new a article. The server would create a resource and give it a name like /articles/1234 and then it would tell the client about this new name by returning a 201 CREATED HTTP code and adding a Location: /articles/1234 header to tell the client where the new resource is. In your scenario, POST isn't a meaningful verb because you always know what the name of your singleton resource is.
DELETE means you remove a resource, and since a resource is identified by a URL, DELETE /measure implies that /measure no longer exists. A subsequent GET /measure should return either 404 NOT FOUND or 410 GONE. In your case, the client can't actually destroy the instrument, so DELETE isn't meaningful a meaningful verb.
Conclusion
So in sum, a RESTful design for your service would be to have PUT /measure with a request body that tells the instrument whether it should be active or not active (paused) and GET /measure to read the current measurement. If you GET /measure on a paused instrument, you should probably return a 409 CONFLICT HTTP status. Your service shouldn't use POST or DELETE at all.
You are still working on a resource, and the way you broke it down sounds good to me. Fielding explicitly mentions temporaral services in the REST chapter:
The key abstraction of information in REST is a resource. Any
information that can be named can be a resource: a document or image,
a temporal service (e.g. "today's weather in Los Angeles")
Maybe it would make sense to give each measurement a unique id though. That way you can uniquely refer to each measurement (you don't even have to store the old ones, but if someone refers to an old measurement you can tell them, that what they are requesting is not up to date anymore).
Building upon the last answer. Here is how you might want to break it down
measures/ - GET all the measures from the instrument (Paginate/limit if needed based on query params)
measures/:measure_id - GET a particular measure
measures/ - POST - Starts a new measure. This returns the new measure ID which you can deal with later.
measures/:measure_id - DELETE - stop the measure.
measures/:measure_id - PUT - update the measure
measures/last_measure - Last measured resource.
Related
Say I have the need to expose a service, where I can request an analysis of a user over a specific range of time (common actions, activities, relationships, etc.).
I would immediately think of this as:
/users/{userId}/analyses - POST
/users/{userId}/analyses/{analysisId} - GET
The problem here, is where the 'analysis' resource comes into existence - it is inherently request-based as it is the service that will do this complex analysis, and also the service that has the most up-to-date state of the user data. In short, it doesn't exist prior to request.
My current thinking has me at three options for requesting an analysis for the first time (with retrieval being the same):
/users/{userId}/analyses?from=2017-01-01&to=2018-01-01 - GET
/users/{userId}/analyses - POST { "from": "2017-01-01", "to": "2018-01-01" }
/users/{userId}/analyses?from=2017-01-01&to=2018-01-01 - POST
I like the GET with query parameters, as I'm requesting a resource, and scoping the user data to be used, until I recognise that the resource could change between requests (based on data on the back end, or processing logic change), and that I would need to call a second time to POST this resource.
I like the POST with the request body, as I'm expecting a resource to be created, until I recognise that the state I've transferred, is not the state I would get back when I retrieve this later, nor is it even the same hypermedia type.
I like the POST with query parameters and no body, as I'm creating a resource and scoping that resource, but I'm still transferring a state that isn't the resource or end media type, and I've seen practically no other examples of POSTs with query parameters.
Anyone have experience with these kinds of actions in a RESTful manner?
In my opinion, using GET /users/{userId}/analyses?from=...&to=... is a good approach.
You request a resource of type analysis which means you have to use HTTP verb GET. You pass parameters to limit the scope. That the resource might change between two requests is not a problem. You request a resource in a specific state and this state might be changed right after your GET request. Compare this to a collection resource where other clients are allowed to POST something.
Using POST would imply that you want clients to create a resource of type analysis with all necessary data, which is from what I understand not true in your case. Your own counter-arguments for the second and third example are correct, in my opinion.
We are currently in the process of wrangling smaller services from our monoliths. Our domain is very similar to a ticketing system. We have decided to start with the cancellation process of the domain.
Our cancel service has as simple endpoint "Cancel" which takes in the id of the ticket. Internally, we retrieve the id, perform some operations related to cancel on it and update the state of the entity in the store. From the store's perspective the only difference between a cancelled ticket and a live ticket are a few properties.
From what I have read, PATCH seems to be the correct verb to be used in this case, as am updating only a simple property in the resource.
PATCH /api/tickets/{id}
Payload {isCancelled: true}
But isCancelled is not an actual property in the entity. Is it fair to send properties in the payload that are not part of the entity or should I think of some other form of modeling this request? I would not want to send the entire entity as part of the payload, since it is large.
I have considered creating a new resource CancelledTickets, but in our domain we would never have the need to a GET on cancelled tickets. Hence stayed away from having to create a new resource.
Exposing the GET interface of a resource is not compulsory.
For example, use
PUT /api/tickets/{id}/actions/cancel
to submit the cancellation request. I choose PUT since there would be no more than one cancellation request in effect.
Hope it be helpful.
Take a look what exactly is RESTful way. No matter if you send PATCH request with isCancelled as payload or even DELETE if you want tickets to disappear. It's still RESTful.
Your move depends on your needs. As you said
I have considered creating a new resource CancelledTickets, but in our
domain we would never have the need to a GET on cancelled tickets.
I would just send DELETE. You don't have to remove it physically. If it's possible to un-cancel, then implement isCancelled mechanism. It's just question of taste.
REST is basically a generalization of the browser based Web. Any concepts you apply for the Web can also be applied to REST.
So, how would you design a cancel activity in a Web page? You'd probably have a table row with certain activities like edit and delete outlined with icons and mouse-over text that on clicking invoke a URI on the server and lead to a followup state. You are not that much interested how the URI of that button might look like or if a PATCH or DELETE command is invoked in the back. You are just interested that the request is processed.
The same holds true if you want to perform the same via REST. Instead of images that hint the user that an edit or cancel activity is performed on an entry, a meaningful link-relation name should be used to hint the client about the possiblities. In your case this might be something like reserve new tickets, edit reservation or cancel reservation. Each link relation name is accompanied by a URL the client can invoke if he wants to perform one of the activities. The exact characters of the URI is not of importance here to the client also. Which method to invoke might either be provided already in the response (as further accompanying field) or via the media type the response was processed for. If neither the media type nor an accompanying field gives a hint on which HTTP operation to use an OPTIONS request may be issued on the URI beforehand. The rule of thumb here is, the server should teach a client on how to achieve something in the end.
By following such a concept you decouple a client from the API and make it robust to changes. Instead of a client generating a URI to invoke the client is fed by the server with possible URIs to invoke. If the server ever changes its iternal URI structure a client using one of the provided URIs will still be able to invoke the service as it simply used one of the URIs provided by the server. Which one to use is determined by analyzing the link relation name that hints the client when to invoke such URI. As mentioned above, such link relation names need to be defined somewhere. But this is exactly what Fielding claimed back in 2008 by:
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. (Source)
Which HTTP operation to choose for canceling a ticket/reservation may depend on your desing. While some of the answers recommended DELETE RFC 7231 states that only the association between the URI and the resource is removed and no gurantee is given that the actual resource is also being removed here as well. If you design a system where a cancelation might be undone, then DELETE is not the right choice for you as the mapping of the URI to the resource should not exist further after handling a DELETE request. If you, however, consider a cancelation to also lead to a removal of the reservation then you MAY use DELETE.
If you model your resource in a way that maintains the state as property within the resource, PATCHing the resource might be a valid option. However, simply sending something like state=canceled is probably not enough here as PATCH is a calculation of steps done by the client in order to transform a certain resource (or multipe resources) into a desired target state. JSON Patch might give a clue on how this might be done. A further note needs to be done on the atomicy requirement PATCH has. Either all of the instructions succeed or none at all.
As also PUT was mentioned in one of the other answers. PUT has the semantics of replacing the current representation available at the given URI with the one given in the request' payload. The server is further allowed to either reject the content or transform it to a more suitable representation and also affect other resources as well, i.e. if they mimic a version history of the resource.
If neither of the above mentioned operations really satisfies your needs you should use POST as this is the all-purpose, swiss-army-knife toolkit of HTTP. While this operation is usually used to create new resources, it isn't limited to it. It should be used in any situation where the semantics of the other operations aren't applicable. According to the HTTP specification
The POST method requests that the target resource process the representation enclosed in the request according to the resource's own specific semantics.
This is basically the get-free-out-of-jail card. Here you can literally process anything at the server according to your own rules. If you want to cancel or pause something, just do it.
I highly discourage to use GET for creating, altering or canceling/removing something. GET is a safe operation and gurantees any invoking client that it wont alter any state for the invoked resource on the server. Note that it might have minor side-effects, i.e. logging, though the actual state should be unaffected by an invocation. This is a property Web crawler rely on. They will simply invoke any URI via GET and learn the content of the received response. And I assume you don't want Google (or any other crawler) to cancel all of your reservations, or do you?
As mentioned above, which HTTP operation you should use depends on your design. DELETE should only be used if you are also going to remove the representation, eventhough the spec does not necessarily require this, but once the URI mapping to the resource is gone, you basically have no way to invoke this resource further (unless you have created a further URI mapping first, of course). If you designed your resource to keep the state within a property I'd probably go for PATCH but in general I'd basically opt for POST here as here you have all the choices at your hands.
I would suggest having a state resource.
This keeps things RESTful. You have your HTTP method acting as the verb. The state part of the URI is a noun. Then your request body is simple and consistent with the URI.
The only thing I don't like about this is the value of state requires documentation, meaning what states are there? This could be solved via the API by providing possible states on a meta resource or part of the ticket body in meta object.
PUT /api/tickets/:id/state
{state: "canceled"}
GET /api/meta/tickets/state
// returns
[
"canceled",
...
]
GET /api/tickets/:id
{
id: ...
meta: {
states: [
"canceled",
...
]
}
}
For modelling CANCEL Action in Restful way :
Suppose we have to delete a note in DB by providing noteId(Note's ID) and Note is a pojo
1] At controller :
#DeleteMapping(value="/delete/{noteId}")
public ResponseEntity<Note> deleteNote( #PathVariable Long noteId)
{
noteServiceImpl.deleteNote(noteId);
return ResponseEntity.ok().build();
}
2]Service Layer :
#Service
public class NoteServiceImpl {
#Autowired
private NotesRepository notesDao;
public void deleteNote(Long id) {
notesDao.delete(id);
}
}
3] Repository layer :
#Repository
public interface NotesRepository extends CrudRepository<Note, Long> {
}
and in 4] postman : http://localhost:8080/delete/1
So we have deleted note Id 1 from DB by CANCEL Action
I read (among others) the following blog about API design: https://www.thoughtworks.com/insights/blog/rest-api-design-resource-modeling. It helped me to better understand a lot of aspects, but I have one question remaining:
How do I deal with functionality that processes some data and gives a response directly. Think, verbs like translate, calculate or enrich. Which noun should they have and should they be called by GET, PUT or POST?
P.S. If it should be GET, how to deal with the maximum length of a GET request
This is really a discussion about naming more so than functionality. Its very much possible to have processed logic in your API, you just need to be careful about naming it.
Imaginary API time. Its got this resource: /v1/probe/{ID} and it responds to GET, POST, and DELETE.
Let's say we want to launch our probes out, and then want the probe to give us back the calculated flux variation of something its observing (totally made up thing). While it isn't a real thing, let's say that this has to be calculated on the fly. One of my intrepid teammates decides to plunk the calculation at GET /v1/1324/calculateflux.
If we're following real REST-ful practices... Oops. Suddenly we're not dealing with a noun, are we? If we have GET /v1/probe/1324/calculateflux we've broken RESTful practices because we're now asking for a verb - calculateflux.
So, how do we deal with this?
You'll want to reconsider the name calculateflux. That's no good - it doesn't name a resource on the probe. **In this case, /v1/probe/1324/fluxvalue is a better name, and /v1/probe/1324/flux works too.
Why?
RESTFUL APIs almost exclusively use nouns in their URIs - remember that each URI needs to describe a specific thing you can GET POST PUT or DELETE or whatever. That means that any time there is a processed value we should give the resource the name of the processed (or calculated) value. This way, we remain RESTful by adhering to the always-current data (We can re-calculate the Flux value any time) and we haven't changed the state of the probe (we didn't save any values using GET).
Well, I can tell you that I know about this.
GET // Returns, JUST return
DELETE // Delete
POST // Send information that will be processed on server
PUT // Update a information
This schema is for laravel framework. Will be most interesting that you read the link in ref
Ref:
https://rafaell-lycan.com/2015/construindo-restful-api-laravel-parte-1/
You should start with the following process:
Identify the resources (nouns) in your system.
They should all respond to GET.
Let's take your translation example. You could decide that every word in the source language is a resource. This would give:
http://example.com/translations/en-fr/hello
Which might return:
Content-Type: text/plain
Content-Language: fr
bonjour
If your processes are long-running, you should create a request queue that clients can POST to, and provide them with another (new) resource that they can query to see if the process has completed.
Say you've got a Person resource, and part of its representation includes a Location value which can have values like "at home", "at school" and "at work". How would you RESTfully expose activities like "go home", "go to work", "go to school", etc? For the sake of discussion, let's stipulate that these activities take time, so they are executed asynchronously, and there are various ways in which they could fail (no means of transportation available, transportation breakdown during travel, other act of God, etc.). In addition, the Person resource has other attributes and associated operations that affect those attributes (e.g. attribute=energy-level, operations=eat/sleep/excercise).
Option 1: Overload POST on the Person resource, providing an input parameter indicating what you want the person to do (e.g. action=go-to-school). Return a 202 from the POST and expose activity-in-progress status attributes within the Person's representation that the client can GET to observe progress and success/failure.
Benefits: keeps it simple.
Drawbacks: amounts to tunneling. The action taking place is buried in the payload instead of being visible in the URI, verb, headers, etc. The POST verb on this resource doesn't have a single semantic meaning.
Option 2: Use PUT to set the Person's location to the state you'd like them to have. Return a 202 from the PUT and expose activity-in-progress attributes for status polling via GET.
Benefits: Not sure I see any.
Drawbacks: really, this is just tunneling with another verb. Also, it doesn't work in some cases (both sleeping and eating increase energy-level, so PUTting the energy-level to a higher value is ambiguous in terms of what action you want the resource to perform).
Option 3: expose a generic controller resource that operates on Person objects. For example, create a PersonActivityManager resource that accepts POST requests with arguments that identify the target Person and requested action. The POST could return a PersonActivity resource to represent the activity in progress, which the client could GET to monitor progress and success/failure.
Benefits: Seems a bit cleaner by separating the activity and its status from the Person resource.
Drawbacks: Now we've moved the tunneling to the PersonActivityManager resource.
Option 4:
Establish separate controller resources for each supported action, e.g. a ToWorkTransporter resource that accepts POST requests with an argument (or URI element) that identifies the Person, plus a ToHomeTransporter, a ToSchoolTransporter, a MealServer, a Sleeper, and an Exerciser. Each of these returns an appropriate task-monitoring resource (Commute, Meal, Slumber, Workout) from their POST method, which the client can monitor via GET.
Benefits: OK, we've finally eliminated tunneling. Each POST means only one thing.
Drawbacks: Now were talking about a lot of resources (maybe we could combine the transporters into one Transporter that accepts a destination argument). And some of them are pretty semantically contrived (a Sleeper?). It may be more RESTful, but is it practical?
OK, I've been researching and pondering this for about a week now. Since nobody else has answered, I'll post the results of what I've learned.
Tim Bray, in RESTful Casuistry, talks about PUT-ing a state field vs POST-ing to a controller which will perform an operation affecting that state. He uses the example of a VM and how to RESTfully expose the function of a "reboot button". He says
"If I want to update some fields in an existing resource, I’m inclined
to think about PUT. But that doesn’t work because it’s supposed to be
idempotent, and rebooting a server sure isn’t. Well, OK, do it with
POST I guess; no biggie.
But you’re not really changing a state, you’re requesting a specific
set of actions to happen, as a result of which the state may or may
not attain the desired value. In fact, when you hit the deploy switch,
the state changes to deploying and then after some unpredictable
amount of time to deployed. And the reboot operation is the classic
case of a box with a big red switch on the side; the problem is how to
push the switch.
So, the more I think of it, the more I think that these resources are
like buttons, with only one defined operation: push. People have been
whining about “write-only resources” but I don’t have a problem with
that because it seems accurate. The reboot and halt buttons don’t
really have any state, so you shouldn’t expect anything useful from a
GET."
Tim seems to settle somewhere between my #3 and #4 option, exposing multiple controller resources, but pulling back from "going overboard" and having separate controller resources for everything.
Tim's post led to another by Roy Fielding (It is OK to use POST) in which he says that for situations where there is a monitorable entity state, and an action to potentially change that state, he's inclined to use POST rather than PUT. In response to a commenter's suggestion to expose the monitored state as a separate PUT-able resource, he says
"we only use PUT when the update action is idempotent and the
representation is complete. I think we should define an additional
resource whenever we think that resource might be useful to others in
isolation, and make use of the GET/PUT methods for that resource, but
I don’t think we should define new resources just for the sake of
avoiding POST."
Finally, Bill de hOra, in Just use POST discusses the specific case of using PUT vs. POST to update the state of a collection resource, and the tradeoffs therein.
I have a RESTful web service which represent processes and activities. Each activity is inside one and only one process.
I would like to represent a "move" operation of activity between the process it is currently in and another process.
I've look at forums and found people suggest to use MOVE operation which is not very standard and other suggest to use PUT but then I'm not sure how to tell the difference between PUT that update and PUT that moves which looks semantically wrong.
Any ideas?
One way might be to represent the move itself as, say, a "transfer" resource (transfer as a noun), and POST a new one:
POST /transfer
With an entity containing:
activity: /activities/4
toProcess: /processes/13
This way, clients are creating new "transfers" which, on the server, handle validating and transferring the activity.
This gives you the ability to add information about the transfer, too. If you wanted to keep a history for auditing, you could add a transferredBy property to the resource, or a transferredOn date.
If using PUTs, you can tell the difference by whether the process of the existing entity matches the new one.
PUT /process1/activity2
process: 2
some_data: and_stuff
To which the logical response (if successful) is
303 See Other
Location: /process2/activity2
Given the available answers I'm not really satisfied with the proposals.
POST is an all purpose method that should be used if none of the other operations fit the bill. The semantics of a payload received are defined by the service/API only and may therefore a solution for one API but not for most ones. It further lacks the property of idempotency which in case of a network issue will leave the client in an uncertainty whether the request received the server and only the response got lost mid way or if the request failed to reach the server at all. A consecutive request might therefore lead to unexpected results or further actions required.
PUT has the semantics of replace the current representation obtainable from the resource (may be empty) with the representation provided in the payload. Servers are free to modify the received representation to a more fitting one or to append or remove further data. PUT may even have side effects on other resources as well, i.e. if a versioning mechanism for a document update is provided. While providing the above-mentioned idempotency property, PUT actually does not fit the semantics of the requested action. This might have serious implications on the interoperability as standard HTTP servers wont be able to server you correctly.
One might use a combination of POST to create the new representation on the new endpoint first and afterwards remove the old one via DELETE. However, this are two separate operations where the first one might fail and if not handled correctly lead to an immediate deletion of the original resource in worst case. There is no real transactional behavior in these set of operations unfortunately.
Instead of using the above mentioned operations I'd suggest to use PATCH. PATCH is a serious of changes calculated by the client necessary to transform a current representation to a desiered one. A server supporting PATCH will have to apply these instructions atomically. Either all of them are applied or none of them at all. PATCH can have side effects and is thus the most suitable fit to perform a move in HTTP currently. To properly use this method, however, a certain media-types should be used. One might orientate on JSON Patch (more reader-friendly) i.e., though this only defines the semantics of operations to modify state of JSON based representations and does not deal with multiple resources AFAIK.