63

So let's say we have something that does not seem best represented as a resource (status of process that we want to pause, stateless calculation we want to perform on the server, etc).

If in API design we use either process/123/pause or calculations/fibonacci -- is that fundamentally incompatible with REST? So far from what I read it does not seem to, as long as these URLs are discoverable using HATEOAS and media types are standardized.

Or should I prefer to put action in the message as answered here?

Note 1:
I do understand that it is possible to rephrase some of my examples in terms of nouns. However I feel that for specific cases nouns do not work as well as verbs do. So I am trying to understand if having those verbs would be immediately unRESTful. And if it is, then why the recommendation is so strict and what benefits I may miss by not following it in those cases.

Note 2:
Answer "REST does not have any constraints on that" would be a valid answer (which would mean that this approach is RESTful). Answers "it depends on who you ask" or "it is a best practice" is not really answering the question. The question assumes concept of REST exist as a well-defined common term two people can use to refer to the same set of constraints. If the assumption itself is incorrect and formal discussion of REST is meaningless, please do say so.

Community
  • 1
  • 1
Andrey Shchekin
  • 19,691
  • 16
  • 89
  • 152
  • Also see [this question](http://stackoverflow.com/questions/17529315/hateoas-how-to-model-link-relations-that-change-state) – Boj Oct 29 '13 at 13:00
  • @Will very good one, I missed it -- thanks. – Andrey Shchekin Oct 29 '13 at 22:20
  • Which question do you want answered? The title of your post ("Is using a verb in URL always bad under REST") or "is [a particular URL design structure] fundamentally incompatible with REST"? Part of the reason you might not be getting the question directly answered is because you're not asking your question directly enough. :) – Jonathan W Oct 30 '13 at 04:40
  • @JonathanW: great point, the title is actually really bad now that I look at it. I'll see if I can improve it. – Andrey Shchekin Oct 30 '13 at 11:17
  • This page's URL contains the title that actually contains "a verb". So this questin makes stackoverflow unRESTful – polvoazul Apr 09 '20 at 05:39

4 Answers4

39

This article has some nice tips: http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api

Quoting from the article:

What about actions that don't fit into the world of CRUD operations?

This is where things can get fuzzy. There are a number of approaches:

  1. Restructure the action to appear like a field of a resource. This works if the action doesn't take parameters. For example an activate action could be mapped to a boolean activated field and updated via a PATCH to the resource.

  2. Treat it like a sub-resource with RESTful principles. For example, GitHub's API lets you star a gist with PUT /gists/:id/star and unstar with DELETE /gists/:id/star.

  3. Sometimes you really have no way to map the action to a sensible RESTful structure. For example, a multi-resource search doesn't really make sense to be applied to a specific resource's endpoint. In this case, /search would make the most sense even though it isn't a noun. This is OK - just do what's right from the perspective of the API consumer and make sure it's documented clearly to avoid confusion.

I personally like suggestion #2. If you need to pause something, what are you pausing? If it's a process with a name, then try this:

/process/{processName}/pause
Community
  • 1
  • 1
ccleve
  • 13,099
  • 21
  • 76
  • 137
  • Yes, that's is a good point (actually that {processName} part was something I was planning to do anyway, just missed in my original question). Actually that blog post is pretty good. I do not really feel it answers my question though -- the author seems to think it is not RESTful, but he does not provide any reasoning (!CRUD is not the same as !REST). – Andrey Shchekin Oct 29 '13 at 22:29
  • I agree ! If all REST services in a API seems like a CRUD, it could be a problem of granularity on API. http://soa.dzone.com/articles/top-10-soa-pitfalls-7-incorrec. “Services are variations of basic CRUD operations (Create, Read, Update, Delete) and do not add any functional value to the basic CRUD operations.” – Eduardo Fabricio Jan 28 '15 at 21:47
  • Because from architecture viewpoint considering perfomance issues there is a dangerous tendency implicit in this approach of Rest like a CRUD. In this case, should all the use cases involving the same information call the same operation ? It could result in overhead of HTTP. "Incorrect granularity of services in your SOA can lead to bad performance, low reuse possibilities, leaky abstractions and services without added business value" Nice topic ! I've been confronting the same questions ! : ) – Eduardo Fabricio Jan 28 '15 at 21:50
  • 2
    The "pause" example is RPC-style not REST. Or is it creating a "pause" resource? – Christian Strempfer Sep 21 '16 at 20:34
  • It's okay to use suggestion #2, however like @ChristianStrempfer states, it's RPC-style and not rest, since pause is not a resource. That's the distinction you need to understand, and that's what the question is about. Of course, in the real world, you will most likely use a combination of of rest and rpc style apis. – Govind Rai Jul 09 '20 at 20:41
39

It's not strictly about nouns vs. verbs; it's about whether you are:

  • identifying resources
  • manipulating resources through representations

What's a resource? Fielding defines it thusly:

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"), a collection of other resources, a non-virtual object (e.g. a person), and so on. In other words, any concept that might be the target of an author's hypertext reference must fit within the definition of a resource. A resource is a conceptual mapping to a set of entities, not the entity that corresponds to the mapping at any particular point in time."

Now, to your question. You can't just look at a URL and say, "Is such-and-such a URL fundamentally incompatible with REST?" because URLs in a REST system aren't really the important bit. It's more important that the URLs process/123/pause and calculations/fibonacci identify resources by the above definition. If they do, there isn't a REST constraint violation. If they don't, you're violating the uniform interface constraint of REST. Your example leads me to believe it does not fit the resource definition and therefore would violate this constraint.

To illustrate what a resource might be in this system, you could change the status of a process by POSTing it to the paused-processes resource collection. Though that is perhaps an unusual way of working with processes, it's not fundamentally incompatible with the REST architecture style.

In the case of calculations, the calculations themselves might be the resource and that resource might look like this:

Request:
GET /calculations/5

Response:
{
  fibonacci: 5,
  prime-number: true,
  square-root: 2.23607
}

Though again, that's a somewhat unusual concept of a resource. I suppose a slightly more typical use might look like this:

Request:
GET /stored-calculations/12381728 (note that URL is a random identifier)

Response:
{
  number: 5,
  fibonacci: 5,
  prime-number: true,
  square-root: 2.23607
}

though presumably you'd want to store additional information about that resource other than a sheer calculation that anyone can do with a calculator...

Response:
{
  number: 5,
  fibonacci: 5,
  prime-number: true,
  square-root: 2.23607,
  last-accessed-date: 2013-10-28T00:00:00Z,
  number-of-retrievals-of-this-resource: 183
}
Jonathan W
  • 3,599
  • 16
  • 20
  • 1
    I feel that the bulk of this answer still tries to answer a different question (how to refactor my approach) -- however that quote is useful. It seems that if I want to use verbs, I should model it as a pause message to process url, not pause url. – Andrey Shchekin Oct 29 '13 at 22:22
  • The quote might be the right answer I suppose, I'll think on it for a bit and then see if I can accept it. – Andrey Shchekin Oct 29 '13 at 22:40
  • I'll rephrase it a bit to directly answer your question. – Jonathan W Oct 30 '13 at 04:19
  • 1
    Is calculations a resource? Can you give me an example of why it is a resource. – variable Dec 17 '19 at 02:49
5

It's considered bad practice to use verbs in your REST API.

There's some material on SO and elsewhere on why and how to avoid using verbs. That being said, there are plenty of "REST" APIs that use verbs.

For your process API, I would make the resource Process have a state field, which can be modified with a PUT.

Suppose GET /process/$id currently returns:

{
   state: "PAUSED"
}

Then you PUT this to /process/$id:

{
   state: "RUNNING"
}

which makes the process change state.

In the case of Fibonacci, just have a resource named fibonacci, and use POST with parameters (say n for the first n fibonacci numbers) in the body, or perhaps even GET with a query in the URL.

Community
  • 1
  • 1
Boj
  • 3,667
  • 2
  • 20
  • 37
  • Thanks, but this kind of sidesteps the issue -- I can update state with a `POST` or `PATCH`, but that just does not feel as intuitive as using a method -- also the state update is not a thing in itself, and can affect many other things. Also `fibonacci` is not really a resource -- you are not getting the code of algorithm itself from that URL, you are getting the calculation result. – Andrey Shchekin Oct 29 '13 at 02:12
  • The question isn't "how can I do that without using verbs in URL", the question is "are verbs in URL still inherently un-RESTful if HATEOAS and other constraints are followed?" – Andrey Shchekin Oct 29 '13 at 02:14
  • Yes, and there are plenty of material on [SO](http://stackoverflow.com/questions/1619152/how-to-create-rest-urls-without-verbs) and elsewhere on why and how to avoid using verbs. That being said, there are plenty of "REST" APIs that use verbs. Go figure :) – Boj Oct 29 '13 at 02:55
  • Well that's my question :) For example your link says "I'm all for the restful approach of using URLs with nouns and not verbs don't understand how to do this" -- I do understand how to do this, but is that actually an absolute requirement for RESTful approach or just a good practice (you obviously should not reinvent get/put/delete, but aside of that)? – Andrey Shchekin Oct 29 '13 at 03:00
  • It will depend on who you talk to. In general, it's bad practice. I believe there's no reason to use verbs given that it's fairly easy not to. – Boj Oct 29 '13 at 03:35
  • "It will depend on who you talk to" -- so your point is that REST does not really exist as a well-defined concept, so it is not even possible to say whether it covers it or not? – Andrey Shchekin Oct 29 '13 at 22:32
  • To modify just a state it involves using something like JSON PATCH, otherwise, you end up sending entire object even if you only want to change the state. It's pretty much CRUD versus Task-based UI. Your solution might work but for more complex requirements sometimes using just PUT isn't enough. – Konrad Aug 14 '18 at 12:34
  • Many hypermedia formats like OData for example support verbs/operations. – Konrad Aug 14 '18 at 12:37
  • for example, you can't solve bank account operations with the update only. Especially if your domain model is complex it's not easy to remotely expose interface to it using just `PUT /resource/` or `PATCH /resource` – Konrad Aug 14 '18 at 12:39
2

The HTTP method is the verb: GET, PUT, POST, et cetera, while the URL should always refer to the noun (recipient of the action). Think of it like this: Would two verbs in a sentence make sense? "GET calculate" is nonsense, where "GET state" is good and "GET process" is better ("state" being metadata for a process).

sherb
  • 3,726
  • 4
  • 32
  • 40
  • 2
    "URL should always refer to the noun" -- should as in "best practice" or as in "RESTful"? Is REST a well defined concept that exists outside of individual understanding of what's good? – Andrey Shchekin Oct 29 '13 at 22:31
  • 2
    How do you map actions that are not in HTTP (basically not CRUD) to this no-verb URLs? E.g. clone action? – Krzysztof Krasoń Jan 30 '17 at 09:07
  • @KrzysztofKrasoń in that case I would use something like `POST /documents?cloneFrom=id-of-document-to-clone-from`. – Germán Medaglia Feb 06 '21 at 19:17