9

I am researching before starting to work on an API for a web-service I am building. The goal is to be very quick and easy to adapt and use for other developers but fairly hidden for clients using a collection of Webapps to make calls to the service behind the API.

It is the first time making an API for more than internal use and I am now wondering researching the standards out there if I should follow RESTful recommendations or rather just go (my instinct) with POST Requests and a JSON-body that holds all the necessary information.

My reasoning against using GET / HTTP-Verbs:

  • The service has fairly fine grained Read/Write control for every single User and DB items. So even a simple LIST request has to be checked not only for credentials but has to do a bunch of internal validation procedures to see if the client is allowed to ask this questions for this particular piece of data.
  • easy implementation: while coding I usually am happy to not have to hop between GET Urls and POST or PUT bodies to get my JSON payload over the line. Appending them to the URL if it is a GET request or into the body if it is a POST or a PUT. So it feels less of a hassle to just go with POST. but I see that is very much my personal taste rather than true for everybody - I am just damn lazy ;-)
  • not really a valid point because we use SSL anyhow, but https://stackoverflow.com/questions/198462/is-either-get-or-post-more-secure-than-the-other#1744404 suggests that it at least, in theory, it might be a little more secure to not force too much sensitive stuff into the URL. In particular, if even READ/LIST requests are considered sensitive for a service, it feels at least a little weird to operate within the URL.

my reasoning for using GET / HTTP-Verbs:

  • Compatibility: Standards are great. And RESTful APIs still seem the most common ones. GET can be easily tested or used by clients from a browser (not sure if that is really a plus, but it might turn out as one)
  • RESTful forces me into a fine-grained separation of concerns through not only URL but also the HTTP verbs (GET/POST/PUT etc). Only using POST I could do the same through URL or early JSON parsing.
  • this blogpost explains a bit about the issues, I found very helpful

Are there any other strong reasons for using the full variety of HTTP verbs like for example REST principles would suggest?

I cannot find any API that does not use different HTTP Verbs. So I guess there must be very strong reasons for that. I suspect the reasons mentioned in the blogpost to be the most relevant, but wonder if there is more to it and if there are other solutions than the one proposed there (first POST, then serving a new GETable resource and returning the URL)

note

this question is similar to mine but comes from a slightly different angle: Is it bad to use POST only on an API?

  • 1
    That blog post describes using POST to create a search request - this is OK as you're creating the search request. even a search can be something that is created. Using GET for search is limited so this fits. I wouldn't missinterpret that and bend it into something where it doesn't fit however. – iwayneo Sep 11 '18 at 13:07
  • Aaaah! Thanks for pointing that out! I DID misunderstand that one. This is sth that for my concrete use case actually is very relevant for my usecase. thank you! – gauguerilla Sep 11 '18 at 13:43
  • 1
    This article strikes a nice balance. It notes that, in order to be fully REST compliant, you also need HATEOAS, but that most applications don't need that level of rigor. As usual, do what makes the most sense from your perspective. – Robert Harvey Sep 12 '18 at 15:04
  • I will add another point against GET or, I'd rather say, in favor of forgetting about the HTTP method and just use one, e.g. POST. If you define each endpoint with a path (name) and body (parameters), you have something similar to a "normal" API, which is basically a bunch of methods, each one with a name and some parameters. I prefer this approach than having to force my endpoints to fit the REST ideal. – Ferran Maylinch Dec 23 '19 at 3:34
  • In my previous comment I forgot to say that I would use POST because it allows body (PUT would work too). With POST body, your methods can be more natural; with GET you're forced to send destructured primitive arguments through query parameters. – Ferran Maylinch Dec 23 '19 at 8:51
11

"What reasons are there AGAINST using only POST HTTP verb in an API?"

You have answered your own question:

The goal is to be very quick and easy to adapt and use for other developers...

If your goal is for other developers to quickly understand and use your API, then use generally accepted practices that most developers would expect. It's as simple as that.

To review your reasons for using POST:

  • I think it would be very strange for a list operation to use POST
  • Your laziness in implementing the API will have a direct cost when other developers begin using it and wonder why every operation requires POST
  • Any hypothetical security risks in using GET are far outweighed by arguments for standards

If you want to experiment with an API that only you will ever use, then feel free to do whatever you wish. But if you want other developers to use it then please save us the frustration and just use the standards.

| improve this answer | |
  • To what standards do you refer? REST is a means to utilize resources on the internet, and JSON Web Services (what software developers often incorrectly call REST) is an architectural style. While this style is commonly used, I doubt that it rises to the level of a "standard." – Robert Harvey Dec 24 '19 at 15:20
  • "I think it would be very strange for a list operation to use POST" - I use APIs that seem to me to be doing that. Typically it's not called a "list operation." Rather, it's done under the guise of providing a "search" mechanism with a POSTable criteria object. – user1172763 Dec 24 '19 at 15:22
  • I meant "standard" as a norm rather than an official document created by a working group, but I updated it to hopefully make it more clear. – Dan Wilson Dec 24 '19 at 15:42
  • List and search are distinct operations to me. A search operation should be able to handle large request sizes for the search criteria, whereas a list operation simply means "get me list of a certain entity." – Dan Wilson Dec 24 '19 at 15:46
5

GET requests are supposed to be idempotent if your using them to post date then it will violate this and be unexpected by users of your api.

| improve this answer | |
  • 1
    They are not only idempotent but referentially transparent, which is a much stronger property. PUT is only idempotent. – Jörg W Mittag Sep 11 '18 at 19:51
4

If you want to make things easy for developers using your api, don't worry about the RESTfulness of various verbs.

Publish A Client

If you publish a client then GET or POST is an implementation detail no-one cares about. If you force the developer to write their own client they need to read you docs to find out whether it's GET or POST.

| improve this answer | |
  • can you extend on that? do you mean: if they have a client they can just model whatever they need around it or use it as an example / demo ? It will have at least 2 clients published with it (for 2 use cases), though those will be mainly for endusers not for developers. though under the hood they would contain everything that the API does for the use cases we are aware of. – gauguerilla Sep 13 '18 at 7:50
  • 1
    if you publish a client then GET or POST is an implementation detail no-one cares about. If you force the developer to write their own client they need to read you docs to find out whether its GET or POST – Ewan Sep 13 '18 at 8:19
  • 1
    Ewan means a client for developers, i.e. an SDK or library. That's very convenient but also a lot of work, especially if you plan supporting different languages... :) – Ferran Maylinch Dec 23 '19 at 8:44
2

I added this comment here, but I wanted to elaborate on my reasoning in an answer.

When we talk about APIs, usually we mean remote APIs, especially HTTP REST APIs. But API stands for Application Programming Interface, so it may mean just a collection of classes/functions (a library).

In my opinion, a remote API is basically an API that is accessed remotely, and it should be designed in a similar way to a "local" API (a library).

If a library contains well defined methods (with well chosen names and parameters), a remote API should be designed in a similar way.

A library API doesn't have the concept of HTTP Method, just a name and parameters, so I think that in a remote API we could ignore the HTTP Method and just use a good name and parameters for each end-point (method).

For the HTTP Method I would choose POST, because we need to choose one, and POST is the most typical method that allows body.

A library method could be:

class Documents {
  DocumentSearchResult findDocuments(DocumentFilter);
}

The equivalent remote API method could be:

@Path("documents")
class Documents {
  @POST @Path("findDocuments")
  @Consumes(MediaType.APPLICATION_JSON)
  @Produces(MediaType.APPLICATION_JSON)
  DocumentSearchResult findDocuments(DocumentFilter);
}

Note that the remote API needs to expose the class/instance and method names via @Path. Maybe a framework could deal with this automatically, so neither @Path nor @POST are necessary (or even the MediaType). But that's another story. Anyway, in that case, the remote API would be declared like this (yes, like the local library interface):

class Documents {
  DocumentSearchResult findDocuments(DocumentFilter);
}

When calling these methods, we would do:

// Local library API usage (pseudo-code, looks like Java)
DocumentSearchResult result = documents.findDocuments(filter);

// Remote API usage (pseudo-code, looks like Dart)
DocumentSearchResult result = await http.post("documents/findDocuments", body: filter);

We could even hide that we're doing a POST, since we want to ignore that, so we could wrap those http calls in a helper function like this, to make it even more similar to a local API call:

// Remote API usage using helper function (pseudo-code)
DocumentSearchResult result = await call("documents.findDocuments", filter);

Having reached this point, we could take it a step further and create a class that wraps this remote call and do this (yes, almost like a local library call):

// Remote API usage using helper class (pseudo-code)
DocumentSearchResult result = await documents.findDocuments(filter);

That could be done manually or by some code generator plugin. But that's another story.

| improve this answer | |
0

I find the POST and PUT endpoints are a little more awkward to test using Curl or a browser's address bar. It's not a huge issue, I admit, but it does exemplify why it's OK to let GET do what it's good at.

| improve this answer | |
  • This would be better as a comment. – Robert Harvey Dec 24 '19 at 15:22
  • @RobertHarvey I thought so, too, except I think this is closer to the real, practical answer than anything else I see here. The answer with the checkmark gets somewhat close, but all that talk of "standards" and "what developers expect" doesn't need to be so theoretical. GET is good because it's easy to work with during development. – user1172763 Dec 24 '19 at 15:25
  • I would agree that it is one consideration, but it's certainly not the only one. – Robert Harvey Dec 24 '19 at 15:26

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.