0

I am designing an API endpoint that runs a simulation, and returns the result.

  • The specific simulation that is run depends on many parameters.
  • There are no side effects. Nothing destructive (creating, updating, deleting) is happening.
  • I don't desire to cache the parameters in the query string of the URL for the user to save, or click refresh.

Should this endpoint accept GET requests, or POST requests?

  • The query string isn't big enough to hold all the parameters. And apparently you aren't supposed to send a payload along with GET requests.
  • There are no destructive side effects (no side effects at all). So POST doesn't seem appropriate either.

What should I do?

Adam Zerner
  • 12,221
  • 13
  • 62
  • 128

3 Answers3

3

Should this endpoint accept GET requests, or POST requests?

I've got some good news for you. REST doesn't care.

Riddle: how would you provide this service on a web site?

You'd probably have some landing page of general interest, and onto that page you would add a link "click here to try the simulator!" When the consumer followed that link, you would provide a representation of a form describing the parameters required for the simulation, with an identifier for an endpoint and an action. The consumer would submit the filled out form, dispatching to your endpoint a representation of the simulator parameters.

A hypermedia API works the same way; the client shouldn't need to know the endpoint, or what method to use. What it needs to know is how to obtain that information from the representation of the form.

If you have a hypermedia API, you can change endpoints, or switch back and forth between http methods, without requiring that the client be updated to match.

There are no destructive side effects (no side effects at all). So POST doesn't seem appropriate either.

I've got more good news for you. Using POST is fine. The current authority for using POST isn't stack overflow, but RFC-7231

The POST method requests that the target resource process the representation enclosed in the request according to the resource's own specific semantics. For example, POST is used for the following functions (among others):

  • Providing a block of data, such as the fields entered into an HTML form, to a data-handling process

Perfect. It's not cacheable, unless you explicitly make it so. It contains facilities for redirecting the user to a cacheable representation of the data, for cases when that makes sense.

What POST doesn't do is communicate to the browser, or the intermediary components, that it is safe to retry a lost message.

Here's what Fielding had to say about this in 2009

It isn’t RESTful to use POST for information retrieval when that information corresponds to a potential resource, because that usage prevents safe reusability and the network-effect of having a URI.

POST only becomes an issue when it is used in a situation for which some other method is ideally suited: e.g., retrieval of information that should be a representation of some resource (GET), complete replacement of a representation (PUT), or any of the other standardized methods that tell intermediaries something more valuable than “this may change something.” The other methods are more valuable to intermediaries because they say something about how failures can be automatically handled and how intermediate caches can optimize their behavior. POST does not have those characteristics, but that doesn’t mean we can live without it. POST serves many useful purposes in HTTP, including the general purpose of “this action isn’t worth standardizing.”

HTTP doesn't specify a method for safe operations that include a payload. It does specify an idempotent method that includes a payload; PUT. Using PUT is unusual in so far as it doesn't really align with the usual understanding of "Create" or "Update", but so long as you are careful about identifiers, I think that it is valid.

Fielding, writing in 2006:

PUT does not mean store. I must have repeated that a million times in webdav and related lists. HTTP defines the intended semantics of the communication -- the expectations of each party. The protocol does not define how either side fulfills those expectations, and it makes damn sure it doesn't prevent a server from having absolute authority over its own resources.

I understand this to mean:

  • The server is not constrained to track the state of the resource as is; it can use an output representation, rather than an input representation
  • The server is not constrained on what access to allow; the resource can be write only. Or getting the resource can provide its input representation again.
  • The server is not constrained on the permanence of the change; "we successfully processed your request (but then immediately reverted the outcome)" is perfectly valid.

From RFC 7231:

A successful response only implies that the user agent's intent was achieved at the time of its processing by the origin server.

In addition, the definition of the 200 status code gives you some room

For the methods defined by this specification, the intended meaning of the payload can be summarized as:

  • GET a representation of the target resource
  • PUT, DELETE a representation of the status of the action;

So I think it's an option that may, upon detailed review, be more suitable to your particular circumstances than POST or GET.

Community
  • 1
  • 1
VoiceOfUnreason
  • 40,245
  • 4
  • 34
  • 73
1

I believe with something like this you would want to have aPOST request and return the user something in the Response in JSON or XML. Im using an API for a site now that sends a POST and I get the data out of the Response, and I to have a lot of parameters I'm passing.

demogorgon
  • 458
  • 4
  • 19
0

First, this API endpoint should be refactored and simplified. HTTP request with a lot of parameters should be avoided, no matter it is a GET or POST or something else. Request with a lot of parameters means very tight coupling between 2 modules -- client side have to assemble very carefully to meet the requirement of server. Also, request with a lot of parameters brings cost on documentation and training.

That said, it has to be a POST if a lot of parameters cannot be avoided. The reason is: although it should be a GET (semantically), GET is not feasible in this situation -- the request with all parameters exceeds the maximum limit of query string. Browser may truncate the query string and break the request.

In summary, it is not a question about what I should do, it is a question about what I have to do, unless the API endpoint is optimized.

shaochuancs
  • 12,430
  • 3
  • 40
  • 51
  • I'm not sure why you say that a request with a lot of parameters means tight coupling. My app is simulating poker hands. I need to pass in parameters that say, "Player 1 may have any of these 30 hands, player 2 may have any of these 25, I want to simulate x times, display these results, with this many dead cards, etc.". Where do you see coupling, and what kind of refactor would you recommend? – Adam Zerner Jul 03 '17 at 04:00
  • @AdamZerner in your case, the client module need to know how to assemble "30 hands" + "25 hands" + "x times" + "dead cards" + information structure, the format/data-structure should be exactly what server expect, a tiny typo in this large data may easily break the request -- this makes the API fragile. – shaochuancs Jul 03 '17 at 04:13
  • @AdamZerner To refactor, can you simplify some model logic? Such as: describe the "30 hands" rule instead of list them all. However, I admit that, it may not work due to business logic requirement. When the model logic cannot be simplified, and a lot of parameters cannot be avoided, POST is the choice. – shaochuancs Jul 03 '17 at 04:14
  • Thanks for the response. I understand what you're saying, and agree in the general sense that this _may_ be a sign that you should refactor, and that in some cases the business logic just requires all of the parameters. However, I don't really see an issue with coupling. – Adam Zerner Jul 03 '17 at 04:28
  • @AdamZerner well, in HTTP request/response situation, the type of coupling between client and server is low ("Data coupling" or "Message coupling" according to https://en.wikipedia.org/wiki/Coupling_(computer_programming)). However, from my understanding, when there are a lot of parameters, it would become a tight-data-coupling or tight-message-coupling. Please correct me if my understanding is wrong. – shaochuancs Jul 03 '17 at 05:47
  • I hadn't known about the concept of data or message coupling - thanks for the info. My understanding of coupling was just content and common coupling, and my impression was that it's tight when there's a lot of it, and loose when there's only a little. I don't fully understand the other types of coupling and their distinctions, but it seems that, by passing info from my client module to the server-side simulator module, it's data or message coupling, which is a loose type of coupling, and I'm not sure that a lot of it makes it tight. – Adam Zerner Jul 04 '17 at 19:57
  • It does seem unavoidable though. The simulator can't guess what type of simulation the client wants performed, and it isn't the case that one parameter can be inferred from the others (like how city and state could be inferred from zip code). Also, I personally am not seeing the downside to data coupling. It doesn't prevent it from being testable. – Adam Zerner Jul 04 '17 at 20:00
  • @AdamZerner yes, data or message coupling is a loose type of coupling. When there are a lot of dependencies (parameters) in data or message coupling, whether it is tight-coupling is controversial. Glad to discuss with you on this topic. – shaochuancs Jul 05 '17 at 01:58