2

We faced an issue with an API "init" method, and trying to understand if we must use GET or POST http method in context of REST.

Preconditions: SPA on the frontend which communicates with our backend using REST API. SPA is meant to work with a 3-rd party service through our API.

Description: When user loads the SPA, frontend calls API method "init". This method does the following:

  1. Check if user registered on the 3-rd party services.
  2. If it does not, register him on that services.
  3. Always return "successful" response (except for internal server errors or problems during the communication with the 3-rd party service).

The question is: can we use GET method for this "init" or should we use POST instead.

These are pros and cons:

Why GET:

  1. We can use it during the page initialization (POST can be used only once the page is loaded)
  2. We do not send any data for this method (except for user token in the headers)

Why POST

  1. It seems like we should use post in such cases, because it provides some basic initialization, checks if everything's alright, and does not return anything, until some internal error is happened.

So we can't decide, in context of REST specification, what is the correct http method for this API call: GET or POST? GET looks more convenient, but we're not sure it's okay to use GET for this API method according to the REST ideology.

  • Don't you have any registration process where to perform the 3rd party regístration too? I have done this during a loging process. The loging was provided by a SSO, so the users had to be registered in the DB the first time they loged in the application. IMO this should be responsability of the server. The client should be agnostic to these sort of details. – Laiv Mar 12 '18 at 18:40
  • @Laiv this is a stateless api, and logging in is provided by general api gateway. So it's not quite good to add some method-specific logic to the login functionality. – Hast Mar 13 '18 at 8:58
  • Well. mine was (still is) stateless too. What matters is whether is idempotent. As the checked answer say. – Laiv Mar 13 '18 at 9:50
2

Key to the question of using GET is whether the semantics of the operation are safe:

Request methods are considered "safe" if their defined semantics are essentially read-only; i.e., 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 purpose of distinguishing between safe and unsafe methods is to allow automated retrieval processes (spiders) and cache performance optimization (pre-fetching) to work without fear of causing harm.

In short: if you are using GET, you are telling clients and intermediary components that they can request the resource any time they like, even if the end consumer hasn't asked for it.

By definition, safe methods are necessarily also idempotent

A request method is considered "idempotent" if the intended effect on the server of multiple identical requests with that method is the same as the effect for a single such request

Meaning, for example, if the client sends a GET request, and doesn't get a response, they expect to be able to send the request again, and repeat it as many times as necessary until an answer arrives.

If those semantics aren't acceptable, then you probably shouldn't be using GET.

RFC 7231 does offer an example of a case where the "safe" semantic is appropriate even though there are significant side effects when handling the request

a safe request initiated by selecting an advertisement on the Web will often have the side effect of charging an advertising account.

From your description, it sounds to me like this could be a case where GET is an acceptable choice.

Agree with the idempotent analysis, but prefer PUT

Certainly "register me if not registered" is an idempotent action. It's not clear to me from the description whether that's an intended part of the protocol, or if it is really an implementation detail.

But the semantics of PUT are more than just "idempotent"; in particular, they imply that the client understands an appropriate representation of the resource. It's not clear from the original description whether the client is expected to be familiar with the details of registration, or if that's an implementation detail of the client.

Furthermore, the most common media type for hypermedia representations is still HTML, and HTML forms don't support PUT. So you either need to augment your representation with code on demand, or you need to replace your representations with some other media type that supports PUT actions.

Of course, many API discard the hypermedia constraint; which makes the PUT method more palatable.

Frontend should not bother about any registration things, it just says us: "okay, I'm here, do whatever you need to get ready to work". Does this mean we should use GET then?

I suspect that is the case: your description reminds me a lot of a read-through cache; with the client asking "give me the current representation", and the server worrying about the details (do we have a current representation? do we need to revalidate it?). A lot of the power of REST comes from its caching semantics.

It may help to review this remark from Roy Fielding in 2002

HTTP does not attempt to require the results of a GET to be safe.
What it does is require that the semantics of the operation be safe, and therefore it is a fault of the implementation, not the interface or the user of that interface, if anything happens as a result that causes loss of property (money, BTW, is considered property for the sake of this definition).

  • Agree with the idempotent analysis, but prefer PUT. – user949300 Mar 12 '18 at 18:43
  • 1
    PUT, puts too much emphasis on the fact that clients should be aware of the registration in the 3rd party service (something additional to my concerns must be done). No matter how you wrap it in an RPC. – Laiv Mar 13 '18 at 8:00
  • > It's not clear to me from the description whether that's an intended part of the protocol This is an implementation detail indeed. Frontend should not bother about any registration things, it just says us: "okay, I'm here, do whatever you need to get ready to work". Does this mean we should use GET then? – Hast Mar 13 '18 at 9:03
4

Your request is making a change to the state of the entity (registration), therefore, get is not an appropriate method.

Use POST.

  • 4
    OTOH, this request, as I understand it, is idempotent, so GET or PUT would be indicated. – user949300 Mar 12 '18 at 18:13
0

For me seems that your method init does too many things.

I will split the functionality of init in two methods:

1) GET to check if user is registered. This is a simple read operation more compliant with the GET method specification

2) In case it is not registered, use a POST to register it as you should write in the server side

  • In theory, perhaps. In practice, it sucks because chaining two requests also doubles your latency. In other words, instead of having a snappy app, you get a slow hog. – dagnelies Mar 13 '18 at 9:13
  • 1
    @dagnelies: Yes, that is a concern. However, it's not clear performance is even a problem, particularly since the POST would only be required on first login. – sleske Mar 13 '18 at 13:05
  • @dagnelies good point but the question was about REST compliance – Arcones Mar 13 '18 at 14:38
0

Here are my five cents.

GET - Requests data from a specified resource. -- W3Schools

You are fooled that you "request" data, because in reality you use some data to validate against.

We do not send any data for this method (except for user token in the headers)

Whats more you are doing some initial logic against it after that.

1.Check if user registered on the 3-rd party services.

2.If it does not, register him on that services.

Also one last evidence GET is not suitable in my opinion as well.

3.Always return "successful" response (except for internal server errors or problems during the communication with the 3-rd party service).

always returning the same result is exactly the behavior you want for GET, but then there is no data which is kinda clunky because you want to get something when you are using GET, right?


Now lets see about POST.

POST - Submits data to be processed to a specified resource. -- W3Schools

So now you are using your token to be processed whats more it would be better if you actually return the resource you've just created(in case of newly registered) or obtained(in case of old user). Usually this is desirable when you are using POST -> You are posting data and you want to see the result of it which to me suits perfectly to you case.

I guess you are using Authorization header to store your token, its not terrible idea to actually have API Gateway in front of your services(APIs) that actually validates this token and sends its claims to the APIs behind, then POST method will be even more obvious in my opinion.

Anyway, to me GET is definitely no go for this case. But I will look forward to see other opinions.

  • Yes, we are using Authorization header, and yes, there is an api gateway between the FE and the actual BE :) I get your point, and it seems to be right. The only thing: our backend encapsulates 3-rd party service's logic, so we can't return any resource (we must not send user id from the 3-rd party service back to the FE). Thus, we just response "okay, user either exists or have been just registered". Which is also not quite good for a restful API. Even if we split this method to "check" and "register", we still won't be able response anything but "success: true". – Hast Mar 12 '18 at 17:35
-1

In the context of REST, I believe this operation is idempotent. A user can only register once, correct? Therefore, PUT is indicated.

Some citations:

https://www.infoq.com/news/2013/04/idempotent

http://restcookbook.com/HTTP%20Methods/idempotency/

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.