HTTP conditional requests

2.3k Views Asked by At

How to implement conditional request with custom condition that checks order status?

Example:

  • User would sent GET /api/order with header "x-if-ready-for-payment": true.
    • If order is ready for payment, response will be order and status code 200.
    • If order is not ready for payment, response will be error message with status code 412.

Is that the right way or did I completely miss the point of the conditional requirements?

2

There are 2 best solutions below

0
CodeCaster On

Conditional request are basically (but read more here) meant to:

  1. Prevent a (heavy) response payload if the client has a cached representation that's still the same as on the server (e.g. If-None-Match, If-Modified-Since)
  2. Prevent an update if the client has an older version than the server (e.g. (If-Match, If-Unmodified-Since)

See also RFC 7232, Hypertext Transfer Protocol (HTTP/1.1): Conditional Requests:

Conditional GET requests are the most efficient mechanism for HTTP cache updates [RFC7234]. Conditionals can also be applied to state-changing methods, such as PUT and DELETE, to prevent the "lost update" problem: one client accidentally overwriting the work of another client that has been acting in parallel.

It's not meant for your custom business logic. Your x-if-ready-for-payment sounds like you're going to need to invent dozens of new headers that only apply to a single or handful of requests.

Determine what problem you're actually trying to solve, and find a different solution.

0
VoiceOfUnreason On

Is that the right way or did I completely miss the point of the conditional requirements?

CodeCaster has the right idea; I want to try a broader approach

HTTP is an application protocol, whose application domain is the transfer of documents over a network -- Jim Webber, 2011

All of the meta data -- the method tokens, the status codes, the headers -- are of the "transfer of documents" domain.


A key constraint of REST is the uniform interface; all resources on the web understand request messages the same way.

GET /api/order

should have the same semantics as

GET /cute/kitten.jpg

Because the semantics are standardized, and because implementations adhere to those standards, we end up with a bunch of general purpose tools (like web browsers) that can be used in a lot of interesting ways -- you can do your shopping and your banking with the same browser that you use to watch videos on youtube, or ask questions on StackOverflow, and it all "just works".

Introducing headers that are specific to a particular server, or a particular resource, swims against that current - you can write a bespoke client that also understands x-if-ready-for-payment, but now we have are coupling to a custom client, rather than being able to use any HTTP standard aware document reader.

New headers can be standardized, of course - we have protocols for adding new HTTP headers to the IANA registry, but if your headers aren't general purpose achieving adoption is going to be an additional headache after registration.


If the client is asking about order status, then what you should probably be doing is including that status in the representation of the resource, for example

GET /api/order
200 OK
Content-Type: text/plain

x-if-ready-for-payment=true

If the client is trying to change the order status, then you use message semantics that indicate we are trying to change the server's copy of the resource, for example:

POST /api/order
Content-Type: text/plain

x-if-ready-for-payment=true

(The content type in my example is there only to reduce ambiguity, it could just as easily be application/x-www-form-urlencoded, or application/json, or application/prs.djoloho+json or whatever....)