162

I am implementing a RESTful web service and one of the available actions will be reload. It will be used to reload configurations, cache, etc.

We started with a simple GET to an URI like this: ${path}/cache/reload (no parameters are passed, only the URI is called). I am aware that data should not be modified with a GET request.

Which is the correct verb to use to invoke an action/command in a RESTful web service?

The reload is a command of the REST web service that reload its own cache/configuration/etc. It is not a method that returns information to the client.

Probably what I am trying to do isn't REST, but it is still something that need to be done this way. The reload method was only a real example that makes sense in the scope of the application and most answers focused on it, but in fact, I just needed to know which verb to trigger an action that doesn't do CRUD, but still changes data/state.

I found this detailed asnwer on Stack Overflow abot the subject: https://stackoverflow.com/questions/16877968/

6
  • 2
    "Reloading" is the sense of an app refreshing the data it's going to display? Is there any difference between reloading and just getting the data again? Commented Nov 2, 2014 at 2:25
  • 3
    @SeanRedmond No, the data is not sent to the client. In fact, is the client saying to the REST web service to execute and internal command (reload). Something like: "a lot of configurations were changed in database, so REST web service, reload them to your memory now". Commented Nov 2, 2014 at 2:46
  • 1
    Cross-site duplicate: stackoverflow.com/q/15340946/319403
    – cHao
    Commented Nov 2, 2014 at 4:58
  • Have you considered using a header parameter on appropriate requests? This sounds very much like a cache refresh...
    – Guran
    Commented Mar 17, 2019 at 19:17
  • In my opinion you're simply not implementing a RESTful web service. RESTful is an architectural principle, and this method of yours simply is not RESTful. Is there any harm in this? Not at all. I always point to this API: api.fattureincloud.it/v1/documentation/dist, all the methods are in POST. It is RESTful? Not at all. Does it work? Yes, it is indeed one of the most used API about e-invoicing in Italy.
    – danidemi
    Commented Dec 6, 2020 at 17:24

9 Answers 9

36

I don't think there is a proper verb for this action because this transaction isn't really "RESTful." The "s" and "t" stand for "state transfer" and nothing is being transferred here. Or, put another way, by the strictest definition, the verbs like PUT and POST are always used with a noun and "reload" just has the verb.

This reload may not be RESTful, but it may still be useful and you'll just have pick a way to do it and live with or explain that it's unusual. GET is probably the simplest. There's a fair amount of skepticism in the comments, though, so you should think about whether or not this reload action is required because something else isn't quite doing what it should be doing.

6
  • I agree that this isn't RESTful but may be useful. I think you should advise a PUT though, because this is probably idempotent but not nullimpotent. Commented Nov 3, 2014 at 21:01
  • @Aaron, the comparison of idempotent and nullimpotent is all well and good, but how do you determine when it's notimpotent? Commented Jul 30, 2015 at 20:01
  • @Craig it's idempotent if running it many times has the same effect of running it once. It's nullipotent if running it once or many times has the same effect on the server as running it zero times. en.wikipedia.org/wiki/Idempotence Commented Aug 1, 2015 at 4:21
  • 8
    @AaronGreenwald “notimpotent” [not-im-poht-nt] [not-im-pawr-tnt] - adjective - 1. A play on words, “not important,” antonym of the adjective “important.” 2. Humor… ;-) Commented Aug 1, 2015 at 6:32
  • 1
    I definitely wouldn't use GET - it's the kind of thing that will work in your development environment but once you go into production you find it's getting cached somewhere by a proxy server you didn't know existed
    – Andy
    Commented Jan 24 at 12:09
122

If you want to be RESTful don't think of the verb to carry out an action, think of the state you want the resource to be in after the client has done something.

So using one of your examples above you have an email queue that is sending emails. You want the client to put that email queue into the state of paused or stopped or something.

So the client PUTs a new state to the server for that resource. It can be as simple as this JSON

PUT http://myserver.com/services/email_service HTTP/1.1
Content-Type: text/json

{"status":"paused"}

The server figures out how to get from the current status (say "running") to "paused" status/state.

If the client does a GET on the resource it should return the state it is currently in (say "paused").

The reason to do it this way, and why REST can be so powerful, is that you leave the HOW to get to that state up the server.

The client just says "This is the state you should be in now" and the server figures out how to achieve that. It might be a simple flip in a database. It might require thousands of actions. The client doesn't care, and doesn't have to know.

So you can completely rewrite/redesign how the server does that and the client doesn't care. The client only needs to be aware of the different states (and their representations) of a resource, not any of the internals.

9
  • 4
    As far as I'm concerned this is the correct answer. Refreshing data on the server is not an idempotent operation, and GET is a completely inappropriate verb to use. PUT is the most appropriate verb as the operation can be thought of as updating the "reloaded status" of the cache to "reloaded".
    – Jez
    Commented Apr 27, 2015 at 15:17
  • @Jez Of the answers here, I prefer this one as well. Sticking with the email metaphor, offhand it does feel odd at first to think of sending the mail by putting it into the "sending" state instead of just sending it (an action). But if you think about it, that's really the same thing as putting it in the "outbox." In fact, the mail system itself is probably queuing it that way internally when you tell it to send. So the API can let you put the mail in the "sending" state, and the API isn't obligated to explain itself beyond that. Commented Jul 30, 2015 at 19:57
  • So by extension, if you don't want the message to go just yet, you put it in the "scheduled" state with a date/time when it should be released. If it isn't complete, you put it (or it is implicitly/by default) in the "draft" state, etc. Commented Jul 30, 2015 at 19:57
  • ...although I think I'd prefer POST to PUT in this case, since PUT is also supposed to be idempotent, but POST is under no such constraint. Commented Jul 30, 2015 at 20:28
  • 3
    You could do that, but ultimately it is trying to fit a square peg into a round hole. There is no reason why the client needs to trigger the server to "reload" anything, that is just poor architectural design. Either the server can update its internal state on each call or at a fixed time interval. Relying on the client to tell the server to reload something independent of any actual request for a resource state is not RESTful architecture. Commented Dec 8, 2015 at 16:16
56

Some of the other answers, including the accepted one, advise you to use a GET (though not very enthusiastically).

I disagree.

First of all, all the others telling you that this is not ideal and not really RESTful are correct. In a proper RESTful scenario, you are manipulating resources on the server and adding, updating, deleting, retrieving, etc those resources. A PUT should send a payload that represents what the resource should be when the request is complete, and POST should send a payload that represents a resource to be added to the server. And a GET should return a resource on the server.

You have an RPC (remote procedure call), which isn't RESTful - you want to DO something on the server. So if you're trying to create a purely RESTful API, you should reconsider what you're doing.

That said, sometimes you do need to bend the rules a bit. Especially if you're developing an internal api that isn't going to be exposed to the public, you may decide that the trade-off is worth it.

If you do, I would recommend a PUT or POST, depending on whether or not the RPC is idempotent or not.

In general, we say that HTTP PUT maps to SQL UPDATE and that HTTP POST maps to SQL INSERT, but that's not strictly true. A purer way to state that is that HTTP PUT should be idempotent and HTTP POST needn't be. This means that you can call the same PUT request as many times as you want with no side-effects. Once you've called it once it's harmless to call it again. But you should not repeatedly call POST requests unless you mean to - each POST changes data on the server again.

In your case, if you need to have this reload function, I'd recommend a PUT because it sounds like it's idempotent. But I would still urge you to consider what the others said about not needing it at all.

2
  • Learned a new word, idempotent, thanks! Your point for using put is spot on and is what I I needed. Is there any such thing as "pure" in the software development world? Thinking the RPC verb was overlooked in the RESTful specification.
    – Michael
    Commented May 12, 2022 at 11:59
  • 1
    This is an important point. Quite often it is an RPC that you want to perform, and HTTP calls are the tools available with which to perform it. This doesn't necessarily mean the system is architected poorly, just that not every valid architectural choice can be encapsulated in the REpresentational State Transfer worldview. Perhaps somebody should go and write an RFC adding a "DO" HTTP method.
    – harperska
    Commented Jun 15, 2022 at 22:43
7

POST and PUT are the HTTP verbs used to submit an entity to a web server. With PUT, the submitted entity is the (new) representation for the resource at the given URI, which doesn't fit what you want. POST is for the traditional form-handler, where the entity is ancillary data for the resource, so that's the winner. The entity would include the command or action (e.g. "action=reload").

That said, the command in question probably shouldn't be exposed via a REST interface. It sounds like the necessity for "reload" arises because data can be changed via some other channel (e.g. filesystem, DB client). Caches should be transparent. Moreover, HTTP requests should be atomic, even taking messages sent over other channels into consideration. Offering a "reload" command for configuration settings seems an unnecessary complexity; requiring it is a brittle design. Exposing "reload" to clean-up after an update via another channel is dirty because one channel doesn't contain the entire conversation. Instead, consider one of:

  • making updates entirely via REST
  • exposing the command(s) to the other channel
  • automating the actions

Some of those options might not be viable, depending on what other restrictions exist.

See also "PUT vs POST in REST".

2
  • Thank you. I removed the "internal" of the edit because in fact the "reload" method is intended to be public. I just tried to mean it refers to the web service itself. I think posting the "action" would be a good approach. Commented Nov 2, 2014 at 3:40
  • @RenatoDinhaniConceição: even without the "internal", it still smells. It might behoove you to ask a new question about whether the design is a good one.
    – outis
    Commented Nov 2, 2014 at 5:02
6

Why not treat the action like a resource. So since you want to update the cache, you would POST a new action in your system.

For purists, you could have a dedicated urls for that. Note that you could extend this and log the actual actions in a database (or whatever storage) with date, status, user, etc... Just my thoughts here.

Generic system-wide operation /actions/{action}

Operation specific to a resource type /actions/{resource}/{action}

Operation specific to a resource /actions/{resource}/{id}/{action}

In your case, the cache is probably system-wide /actions/reload_cache

5

When facing a similar scenario to the one you described - wanting to use a verb as part of a REST endpoint - I typically solve it by transforming that verb into a noun.

So instead of:

GET ${path}/cache/reload

I'd do a:

POST ${path}/cache/reload-request

This will force a shift in how you think about your action. You should now think about how to create a new resource that represents the reload request. Since HTTP requests are normally short-lived this creates a nice abstraction that allows you to return a resource containing id and status and send the actual action to be processed in the background. Then the caller can check later if the request has been processed by doing:

GET ${path}/cache/reload-request/{id}

Or even cancel the request by doing:

DEL ${path}/cache/reload-request/{id}

Sometimes your action is so quick and simple that just returning 200 OK with an empty body is enough. That tells the caller you've taken the request to execute the action and processed it already, without the need for further calls to check the status.

1
  • I like that idea. Typically you are really able to express the action as a "thing" instead that can be taken as a resource and - possible this is required later - identified and tracked.
    – webjunkie
    Commented Apr 21, 2022 at 9:49
4

I would argue why a client request would explicitly need to make a call to refresh something like that. It sounds like that should either be hidden logic on a more typical implementation of GET (I.e. Pull data, but the service makes a refresh on the data before it is pulled), or by another trigger in the backend away from the client.

After all, the data/config would only need to be current on subsequent calls, so I would lean more towards a lazy vs eager call for a data refresh. Obviously I am assuming a lot here, but I would take a step back to reevaluate the necessity of such an explicit and standalone call.

3
  • Look at my edit. "reload" is not a command that returns data. It refers to the REST web service itself. In general terms, my question refers about triggering actions in a REST web service. Other example can be: email_queue/stop_sending_emails. I am justing giving a command to something using a RESTful interface. Commented Nov 2, 2014 at 2:52
  • 5
    I still agree. Invoking SIGHUP on a local process makes sense, since the computer should trust someone logged in locally who has access to that signal. But for a stateless, Internet-accessible protocol? Perhaps the web service should automatically reload as necessary via polling or file monitoring. This call should be completely unnecessary.
    – user22815
    Commented Nov 2, 2014 at 3:50
  • 1
    I agree. Things like configuration and caching are meant to be transparent to the client. Maybe you should give us a more concrete description of a situation in which your endpoint would be called. Commented Nov 3, 2014 at 21:26
1

Which HTTP verb should I use to trigger an action in a REST web service?

When considering the details of a REST service, it is often useful to consider this heuristic: how would you implement this with a web site?

HTML can only natively describe GET and POST requests. So we can start are search there.

Is GET appropriate? To answer this question, we need to think about the assumptions that clients and intermediate components are allowed to make about GET. The semantics of GET are safe

the client does not request, and does not expect, any state change on the origin server as a result of applying a safe method to a target resource. Likewise, reasonable use of a safe method is not expected to cause any harm, loss of property, or unusual burden on the origin server.

The implication, therefore, is that the clients and intermediate components have discretion to invoke a GET request as frequently as necessary to satisfy their own concerns. Spiders can GET resources indiscriminately to update their indexes. Caches can pre-fetch. On an unreliable network, lost messages can be retried as frequently as necessary to ensure at-least-one response.

It will be used to reload configurations, cache, etc.

If these are expensive things to do, then maybe you don't want the clients to issue these requests at their own discretion.

POST, on the other hand, is effectively unconstrained -- this greatly reduces the assumptions that generic clients are allowed to make. You don't get components making speculative POST requests because they would be faulty to do so -- nothing in the standard says that's OK.

PUT, PATCH, DELETE... these are unsafe methods with more specific semantics than POST; whether or not they are appropriate is going to depend on your resource model.

An important idea to keep in mind is that the HTTP methods belong in the document domain (See Jim Webber's 2011 talk), the effects you are describing are probably not part of the document domain, but are instead side effects invoked when the documents are changed. That gives you a lot of freedom in terms of how you organize your documents to get work done.

1

What about PATCH?

https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH

A PATCH request is considered a set of instructions on how to modify a resource. Contrast this with PUT; which is a complete representation of a resource.

A PATCH is not necessarily idempotent, although it can be. Contrast this with PUT; which is always idempotent. The word "idempotent" means that any number of repeated, identical requests will leave the resource in the same state.

Not the answer you're looking for? Browse other questions tagged or ask your own question.