How do you feel about the "misuse" of HTTP methods?

twitter logo github logo ・1 min read

In case you're not sure what the difference between GET and POST in HTTP are (or what that sentence even means), here is a great post from today:

It got me thinking that there are definitely situations where folks hack on different methods to create the desired outcome. Sometimes GET is used alongside a "url param" password of sorts in contexts like one-click actions from an email (for unsubscribing or otherwise).

I also notice that, for example, Algolia uses a POST request for searches where I would expect a GET request. I think this is for mild performance improvements, or simply for consistency due to the fact that some of their requests probably should be triggered via POST.

Anyway, what are your thoughts about when to use the "wrong" method, or if this is ever advisable?

twitter logo DISCUSS (32)
markdown guide
 

A one-time action URL as a GET request does break the idempotency property, but what else are you going to do?

At the end of the day the pragmatic solution is best. Solve the problem while introducing as few side problems as possible. And keep it simple -- that's my general philosophy.

The real rabbit hole of the HTTP methods debate is once you get into the semantics of PUT/DELETE and frankly I don't see the advantage.

GET and POST have the simplest semantics and you can build APIs that are super clear, pragmatic and easy to use with just those two methods, occasionally bending the rules when it's helpful but keeping things as predictable as possible.

 
 

That article doesn't give a strong argument against ONLY using get/post IMO. His main point is to maintain idempotency, but you don't need all the extra verbs beyond get and post to do that.

 

If I have a large team of developers that are building a REST API, I enforce REST guidelines to ease communication among developers as well as follow the principle of least surprise.

If it's just me on an application of my own design, I just post everything, as I don't need to communicate how my API works to anyone, and I'll rarely surprise myself. If for some strange reason I were to bring on other developers and/or sell one of my apps, I would spend an afternoon converting all my endpoints to a canonical REST interface. I would even make sure trailing slashes were dealt with properly.

 

Misuse of what exactly? A set of poorly defined methods designed in a vaccuum by people who clearly didn't consider UI design nor proper web architecture and long before modern web apps were even considered.

The whole web stack is a giant workaround. Do whatever you want with HTTPs methods -- provided it works. Nobody can fairly judge you as doing anything wrong.

 

While I appreciate the rage

designed in a vacuum

is patent nonsense. It was designed on the fly as the World Wide Web took off in the 90s - as far from a vacuum as you could get. As is

The whole web stack is a giant workaround

The 'web stack' is trying (or at least was trying) to leverage the incontestable success of the WWW as distributed hypertext (in the 90s) into distributed systems architecture. That was the whole point of REST. Yes it's a kludge - all the great and useful things are kludges. But it's a kludge built over the most successful, open and transparent transport protocol of all time. Most of the really workaround solutions - things like SOAP and RPC over XML - are pretty much toast now, although everyone keeps telling me that RPC is cool again.

Nobody can fairly judge you as doing anything wrong.

... sure, although they may fairly judge you as doing something unexpected.

 

Agreed! Lately I've been using POST for everything in my API's. Why? Because I'm not going to design my API's around transport protocols! Now they can be consumed by literally anything. UDP, TCP, websockets, domain sockets, cluster messaging and more. There can be different transports internally/externally and yet it's the same API.

 

“The whole web stack is a giant workaround.” Yeah baby! That how you say it!

 

I think that REST is not perfectly suitable for contemporary applications, which are simply too complicated for it to handle gracefully. The simplest example I can give is a /login, where no conventional method works (you're not GETting information, not POSTing nor PUTting some payload [and dear God don't use DELETE]). The ultimate solution would be a combination of REST and RPC of some sort, in my mind.

Lately I've been getting into GraphQL and I gotta say I fell in love with it, as I feel it is the replacement of REST I've looked for. They opted to put the whole query in a POST request (be it GET, POST, PUT or DELETE equivalent), but in a nice structure that is easy to follow and manage.

 

Actually the more I build complex apis, the more It messes my head around to stick with REST because of consistency issues.

For example, I would have a route to display all the shoes in a shoe store in GET /api/shoe, but getting the users liked shoes would be used through Post /api/shoe/liked because I authenticate the user with a JWT and I prefer to use a POST parameter because of the limit in GET queries and the fact post parameters are less easy to sniff than get... But this would work fine in GET because my tokens are not so long and my urls quite short but I do this to prevent any issues.

Also, it has for a moment make me wonder how complex it is to stick with only GET,POST,PUT,DELETE. An example is when you want to provide an "undo" feature.

Say you can trash a comment, or remove it permanently. Trashing would be seen as the equivalent of soft deleting, so why not use DELETE. But then you have the actual deletion, or maybe named destruction. Will you use DELETE to do this? Then the classic REST schema does not work anymore.

I feel like you, today REST gets less and less optimal for complex apps, GraphQL seems to be more suited.

 

Setting REST aside for a moment, the main issue with not using GET for read only requests is that you forego HTTP caching, which is a huge deal in many cases.

I'm definitely pro trying to stick to the standard but also I think it's okay to bend it if necessary.

I don't agree with people saying "fudge it" on principle, just because it seems that they don't want to learn HTTP in the first place :D

 

I guess it depends on what you're doing. Logic I use for determining things like this:

  • If there's a method that exactly matches the required semantics, use it. Usually, this translates to GET, PUT, DELETE, or PATCH in my experience.
  • If it doesn't modify server-side state and is cachable, it's a GET request.
  • If it does modify server-side state, but is idempotent, it's a PUT request unless some other request has specific semantics that fit better.
  • Otherwise, it's a POST request, probably with headers to prevent caching.

The thing is, in reality, if your request doesn't actually fit the first three cases, there arguably isn't a HTTP method that does exactly what you want, and it just makes the most sense to use the de-facto standard catch-all method.

 

HTTP method semantics are really important in some scenarios for caching. POSTs are often ignored by caching proxy's, and the request body for GETs may be dropped/ignored as it's not expected as part of the HTTP/1.1 specification. Aside from technical/practical reasons for using proper method semantics, the misuse of methods can indicate weak API design and it's usually possible to adhere to the standards without much ambiguity. There are scenarios where this isn't true, RPC calls for example. IMO there's probably room for a more headers to reduce the overuse and ambiguity of POST, but we've had the existing methods for so long that it would be difficult to introduce new ones without breaking a ton of things.

 

I had used non-standard methods like PUT and FETCH in a REST API app I'd created as a side-project some time back.

But now that I think retrospectively, its not really needed. You can simply use one POST method with "action" or something as a parameter corresponding to the REST action you want (such as create, delete, update or insert).

 

Hmmm.. Building good REST api is tricky and building API for internal or external API can be a nightmare.

I find that if they are using either OpenAPI specifications and related tools or Postman.

They are serious in API development work.

Lastly having example like Auth0, Twilio or Salesforce is really a good leader to copy their design concepts.

 

Probably the main technical reason why I use the "wrong" method (POST) for read-only queries is because of all the layers of caching that I have to bust with GET requests. My internal APIs are typically for live data, so caching is not desirable. I've done the efforts before to use GET because it was the "right way". But in the end it was a lot of yak shaving that I could have avoided just by using POST.

Whatever people later appropriate HTTP methods to mean (e.g. REST), they already have pretty well-defined behaviors to most web servers. For example, GET requests also have a limited amount of data they can send (whatever length URL the web server will accept). And URLs are typically logged (also undesirable in many cases). So rather than ideologically trying to match up what someone says I should do, I try to match up the actual functionality with my needs.

That's also why I arrived at using request/reply messaging instead of REST. And using commands and queries instead of GraphQL. These allow me to focus on what the user is trying to learn and accomplish rather than being an exercise in munging data.

 

I don't mind people using the "wrong" method.

What DRIVES ME FREAKING INSANE is when they do this but tell me it's a "REST API".

 

Like anything else, there are the die-hard theorists who say never break the pattern. But that isn't a good enough reason to listen.

A good reason to do things "correctly" is that your tooling will expect you to do it correctly. End users, if it's a public API or even public inside your company, will expect you to do it correctly. If you do it in a non-standard way, it may cause you to have to write additional documentation, which is an expense.

You have to weigh out each situation. When making an API, I'd stick to the convention unless I had a particularly good reason not to. One example is the GET with a token for password reset. Just obviously be aware of the implications - e.g. query params expose data. Make sure it's not sensitive or short-lived.

And writing a prototype isn't a good enough reason to skip convention. Many a production app is still running its prototype code.

 

If I recall from Algolia I think there's also side effects from your searches, so POST would make more sense there. I have mixed feelings about it I guess. Most of the time I think it's a good idea to stick to GET only returning stuff, and POST when you want to change the state of something on server side. Oh, yeah, and when you GET stuff then your params show up in your search history, so if you're including things like auth tokens or (gasp) password, that's very much not a good idea.

 

It depends what it's intended to be used by and how it's misused.

GET requests shouldn't make changes. But I've been somewhere this was done internally by an API gateway and it was fine, and made it easy to test by pasting URLs into the browser address bar. I objected to this, but it didn't end up causing any problems.

However if there's a possibility these misused GET requests will be cached or spidered (in other words, if it's a public API, for some value of public), then it will probably lead to things breaking. I've heard a horror story of things getting deleted by web crawlers.

If a POST request is treated as "posting a command to an endpoint" I don't think it would cause problems as long as it's well-documented what the expected behavior is, even if that command is the equivalent of "give me information" or "delete something".

 

I don't give a fuck about methods purity, but there is a few properties to follow

  • What goes in GET parameters must be inconsequential (do not trigger any write)
  • Secrets are better in POST (as POST body are not usually logged nor visible)
  • Post friends like PUT and PATCH can have meaning for your app
  • Also GET and POST get cached differently and that's an important property as well
 

When I was building software for the Army, we learned that certain request methods were blocked. For us, it was just one more drop in the it is what it is bucket.

Recently I've discovered that some of our applications return a failed authentication response as a 200 OK along with a validation messages object that says exactly the opposite.

It's my preference to be bothered by this type of thing. People meet, discuss, and make decisions about these things, so who am I to say, "Thanks for the suggestion, but I'll be going my own way."

Sometimes, though, it is what it is.

 

I feel dirty when I have to admit this, but doing a route that should be a GET via POST because the URL and the query parameters could become to long. We had a long discussion about this and were looking at how others handled. We found out Google basically said they did the same thing to get around the limits, so we went forward with the dirty feeling.

 

I don't care. Not at all.

What I mean by saying this is that the problem, in this situation, dictates the solution. @nielsoftware seems to have a great workflow while @dorshinar has a great point relative to API. The commonality seems to be scope and scale.

This concept irks me. Scope and Scale are restrictions (constructs) from an engineering point of view. Forcing a different paradigm among constructs is a basic programming no-no. I'd say the issue is a) under engineered and is a one-off b) under engineered and perceived to be a one-off c) over engineered and has too many options d) lacks clarity in it's definition.

my 2 cents

 

GET should never have side effects. It is perfectly fine to use as URL to unsubscribe or confirm things in an email but visiting this URL should always show a form to POST the confirmation.

 
 

That's a Great thread, would be eagerly waiting for responses...

 

We haven't fully announced this yet because we want to add some follow-on functionality for managing notifications but you can now "follow" threads and get notified of each reply via the post's "three dots" menu.

😋

 

I briefly worked at one company where a senior developer forced everyone to use "GET" only for static page requests and "POST" only for api calls.

It was insanity.

 

My side-project revolves around an API that uses GET requests with "method=post" URL parameters instead of HTTP methods so I do have strong feelings about it but I better keep them to myself

 
 

Purist kind of annoy me. If it is my api and I'm the only one interacting with it, I'm gonna do what I need to do. If it is someone else's api, I'll use the verbs they insist upon.

Classic DEV Post from Feb 6

What's your goto motivational quote?

What's your goto motivational quote?

Ben Halpern profile image
A Canadian software developer who thinks he’s funny.

Sore eyes?

dev.to now has dark mode.

Go to the "misc" section of your settings and select night theme ❤️