2

I've encountered API that tell as being "restful" but then I see resources with verbs instead of reserving those said verbs to the METHOD. Here's some (paths shortened so only the relevant method and path parts are shown):

  1. POST /things/84/lock
  2. POST /things/84/unlock
  3. POST /things/84/edit
  4. POST /things/prepend (Adding to the beginning of the ordered collection)

Why doesn't it make sense to do instead:

  1. LOCK /things/84
  2. UNLOCK /things/84
  3. PATCH /things/84 or EDIT /things/84 (I prefer the first one)
  4. PREFIX /things or PREPEND /things

I've only been told again and again that this is not restful because it must only use GET, POST, PUT, DELETE and PATCH to remain restful.

What logical explanation exists for having verbs in the path section of the URL for restful API?

Notes:

  1. I can't show you real life examples so I won't be pointing fingers at anybody.
  2. As for proxy limitations excuse I've been experiencing. It was valid while no workaround existed. Nowadays, most modern frameworks have mechanisms to allow method override using query variables or headers (with de-facto standards, even).
  • 2
    Partial answer as to why someone might have put the "verbs" in the url: it's quite possible that the API was written before "modern" frameworks that could handle something other than GET and POST. And not everyone wants to (or has time to) rewrite / upgrade their API every time technology and frameworks take a step forward. Legacy code is a thing, a huge thing. – Becuzz Feb 16 '18 at 14:39
  • 1
    No, that is definitely not RESTful. In REST, an URL should indicate a resource but not an action. There might be good reasons for the design, but it is wrong to call it RESTful. – JacquesB Feb 16 '18 at 15:58
  • 1
    Change your point of view. The aim of REST over HTTP is to allow any application with a http client to consume your API. HTTP clients don't care what is in the URI path. They care about speaking http. LOCK, UNLOCK, PREFIX are not in its vocabulary. Basically these won't make sense for anyone but for your own system. If you don't want your API to be consumed world-wide by any http client, then go with these verbs. But, how whatsisaname say. If you don't need the ergonomy of the WWW, then go with RPC, where you can tunnel any verb you want and still be www-firendly – Laiv Feb 17 '18 at 7:24
  • 2
    In other words HTTP is a protocol for machines not for humans. So stop thinking in REST as if It was going to be read by humans. HTTP clients are far to be it. – Laiv Feb 17 '18 at 7:30
  • 1
    Worth reading – Laiv Feb 17 '18 at 12:24
2

Is it restful to have verbs on the HTTP path instead of the HTTP method?

Yes. REST doesn't care what spelling you use for your identifiers.

I've only been told again and again that this is not restful because it must only use GET, POST, PUT, DELETE and PATCH to remain restful.

One of the REST architecture constraints is the uniform interface; describing it in his thesis, Fielding wrote

By applying the software engineering principle of generality to the component interface, the overall system architecture is simplified and the visibility of interactions is improved. Implementations are decoupled from the services they provide, which encourages independent evolvability....

There's nothing particularly magic about [GET, POST, PUT, DELETE, PATCH]. A very long time ago, that list would probably be [GET, HEAD, POST], because those were the only methods that had been standardized in RFC 1945. The others were documented with this warning:

This appendix documents protocol elements used by some existing HTTP implementations, but not consistently and correctly across most HTTP/1.0 applications. Implementors should be aware of these features, but cannot rely upon their presence in, or interoperability with, other HTTP/1.0 applications.

The interoperability is key, in that it means that clients and servers and intermediary components that share an understanding of the message semantics can all cooperate together to produce a result -- without needing to understand the payload of the message.

Today, we have a method registry, with many different methods that you might want to use, including (as it happens) LOCK and UNLOCK. So, assuming your semantics agrees with those documented in the registry, you could use them.

In circumstances where you control both the client and the server, limiting yourself to the registered methods is less critical than it would be otherwise.

If you are targeting clients that understand code on demand, then you can give a generic client a link to download your client code to interact with your services.

4

There are a lot of problems with using custom HTTP methods that mean it's rarely a good idea. Some of these are:

  • Some proxy servers and firewalls will not forward requests using them
  • Implementing them often requires custom server configuration that may not be possible on shared hosts (thus preventing the use of such services)
  • The semantics of the method may be unclear (is a call to your custom method idempotent? We know that a call to a PUT method should be, and that a POST method likely isn't, which is a clear benefit of using those two method types)
  • A key feature of RESTful services is the ability to discover operations that can be performed on a resource automatically (i.e. HATEOAS). But the standard techniques (e.g. the use of link elements in xml documents or JSON-LD) for doing this only provide the means of specifying the URI to use for such an operation, not what request method should be used. This therefore impacts discoverability of your API.

Generally speaking, using a /noun-type/specific-noun-identifier/verb structure is easier and more understandable than custom HTTP methods, so why go to the effort when it has potential negative consequences?

  • 1* Is moot for nowadays, as per what I mentioned in the question. 2* On the receiver end, you mean? If so, how so? It's just a string! 3* The current standard rfc states that all methods not specified should be assumed to be non-idempotent and not safe. Regardless, an OPTIONS method call can clarify that. IMO, This is the only one that can be used to opose. 4* Use the OPTIONS method. You know the resource exists, now just ask what it allows you to do to it. Do note I never mean to have methods to do operations that are already specified. This is for things not specified in RFC. – brunoais Feb 16 '18 at 16:22
  • "1* Is moot for nowadays" -- is it? The last time I worked in an environment that had a firewall that prevented such things was only a couple of years ago, so I'm pretty sure there must still be some locations where it happens. "how so? It's just a string" -- yes, but server configuration may prevent it being passed to your processing scripts (e.g. PHP has an option http.request.methods.allowed that can be used to limit the allowed methods). "Use the OPTIONS method" -- which requires an extra round trip to the server. Yes, of all these problems only the first is a showstopper, but what... – Jules Feb 16 '18 at 16:37
  • ...do you gain by working around them? – Jules Feb 16 '18 at 16:37
  • 1*: It is. On the server, you can control. On clients with IT stuck in the past, there's workarounds. 2*: Just change the server configuration. 3*:The OPTIONS request only needs to be used once when making the API calls. As for gains: I gain semantics. You do X on Y. For example, I don't POST onto a lock resource. I lock a resource. I don't post an item into a prepend resource of a collection. I prepend a document on a resource collection. Do these examples help? – brunoais Feb 16 '18 at 17:02
  • 1
    1*: I work every day with customers that have proxy rules regarding HTTP methods (PUT and DELETE overall). They also block X-like headers. 2* changing http severs is not always in your hands. And not always you are totally aware of the vulnerabilities you might be exposing a system due to a uncommon configurations. 3* if you want your own semantics, use other protocols that also works over tcp/ip. Or like has been commented, do use other semantics as RPC. HTTP has no more methods for a reason. The protocol should be untied from the "business" that operates over. – Laiv Feb 17 '18 at 9:24
1

If you wish to use a custom "verb," there is a mechanism in place for this already: verb tunneling via the the x-http-method-override header. This gives you the benefits and avoids most of the pitfalls that Jules listed.

It is possible to instruct network intermediaries (proxies, firewalls, and so on) inspecting traffic at the application protocol layer (for example, HTTP) to block requests that contain certain HTTP verbs. In practice, GET and POST verbs are rarely blocked (traditional web pages rely heavily on these HTTP methods), while, for a variety of reasons (such as security vulnerabilities in prior protocols), other HTTP methods (PUT, DELETE, and so on) are at times blocked by intermediaries. Additionally, some existing HTTP libraries do not allow creation of requests using verbs other than GET or POST. Therefore, an alternative way of specifying request types which use verbs other than GET and POST is needed to ensure that this document works well in a wide range of environments.

To address this need, the X-HTTP-Method header can be added to a POST request that signals that the server MUST process the request not as a POST, but as if the HTTP verb specified as the value of the header was used as the method on the HTTP request's request line, as specified in [RFC2616] section 5.1. This technique is often referred to as "verb tunneling".

  • Of course, doing so will raise the blood pressure of the Church of REST's members. – whatsisname Feb 17 '18 at 3:48
  • REST are achitrctural properties and constraints. It has nothing do with the protocol in use. Anyways, the trick commented here is addressed to bypass constraints, not to pass forward custom verbs. If you have to do so, go RPC. Is still the same, but with your own semantics. – Laiv Feb 17 '18 at 7:43
  • @JohnWu Although you are right, you are not answering the question. – brunoais Feb 17 '18 at 10:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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