What you are actually doing when making a specific kind of request is assuming the actual properties match the documented properties and acting accordingly.
A QUERY seems to be no more than a POST that documents it is idempotent. Furthermore, you should only QUERY a resource that has advertised it is idempotent via the “Accept-Query” header. You might as well name that the “Idempotent-Post” header and then you just issue a POST; exactly the same information and properties were expressed and you do not need a new request type to support it.
Your GET request can modify state. But if your request exceeds a browser’s timeout threshold, the browser will retry it. And then you get to spend a few days debugging why a certain notification is always getting sent three times (ask me how I know this)
Similarly, you can put a body on your GET request in curl. But a browser can’t. And if you need to move your server behind cloudflare one day, that body is gonna get dropped.
This is false.
By design QUERY is both safe and idempotent. In the context of HTTP, safe means "read-only", whereas idempotent means that a method does not introduce changes on the server, and thus many requests have the same effect of posting a single request.
The fact that the semantics of an operation is deemed safe has far-reaching implications in the design of any participant of a HTTP request, including firewalls, load balancers, proxies.
> You might as well name that the “Idempotent-Post” header and then you just issue a POST;
This is outright wrong, and completely ignores the semantics of a POST request. POST requests by design are neither safe not idempotent. You do not change that with random request headers.
Outright wrong. You are allowed to handle POST requests in a safe and idempotent way. In fact, the existing usage of POST to query, the literal impetus for this proposal, has exactly that behavior.
What you are not allowed to do is assume that any arbitrary POST request is safe and idempotent.
Only a endpoint that is documented to support POST and that is documented to be idempotent and safe should be sent a POST with request body and expect a response body and be idempotent and safe.
In comparison, only a endpoint that is documented to support QUERY (which implicitly is documented to be idempotent and safe) should be sent a QUERY with request body and expect a response body and be idempotent and safe.
Do you not see how similar those two are?
In fact, you could trivially make every endpoint that handles QUERY just do the same thing if it gets a POST. So why should the client have to care what request type it sends? Why make a new request type?
Of course we should want to define a standardized QUERY server endpoint behavior and document whether a server endpoint has QUERY behavior on POST; that is valuable, but that should be left distinct from the client protocol and constraints.
The only benefit I can see for the client to distinguish QUERY from POST is that it allows intermediate layers to know the request is expected to be idempotent and safe on the incoming edge. The outgoing edge is not benefitted because the server can easily tag things appropriately.
I guess a cache can use that information to only begin allocating a cache entry if the client attempts a QUERY thus saving it from tentatively recording all requests on the chance that the server will say that the actual request that occurred is safe? And that is assuming that the cache does not coordinate with the server to just pre-know what endpoints are safe and idempotent. In that case all the cache would need to do is parse the location to verify if it matches a safe endpoint. So your benefit of adding a new request type is you get to “unga-bunga is QUERY” instead of doing some parsing and matching overhead.
Seems like a weak benefit relative to the benefits of a simpler and more uniform client protocol.
You clearly have no idea about what you are discussing. The definition of HTTP verb semantics clearly defines the concept of safe and idempotent methods. You should seriously learn about the concept before commenting on discussions on semantics. If that's too much work, RFC 9110 clearly and unambiguously states that only the GET, HEAD, OPTIONS, and TRACE methods are defined to be safe. Not POST.
It's completely irrelevant if you somehow implemented a POST method that neither changes the state of the server nor returns the same response whether you invoke it once or many times. All participants in a HTTP request adhere to HTTP's semantics, and thus POST requests are treated as unsafe and non-idempotent by all participants. That affects things like caching, firewalls, even security scanners. The HTTP specs determine how all participants handle requests, not just the weekend warrior stuff someone chose to write in a weekend.
It's clear what POST returns, so... perhaps QUERY is more similar to it in that sense?
When considered abstractly, POST is just a request body and a response body. This is obviously powerful enough to define any behavior you want; it is just a channel flowing a nearly arbitrary amount of opaque data between the client and server.
However, this kind of sucks because it does not define or constrain the behavior of the client or the server. QUERY says that the server is intended to interpret the request body as fetch parameters and return a response body as the fetched data, and further guarantee that the fetch is safe/idempotent. This is very useful.
My disagreement is that there is no good reason for the client request format to care. You should “POST” to a “QUERY” endpoint. The fact that this endpoint guarantees QUERY behavior is just part of the documented server interface in the same way that certain endpoints may not support PUT. This is a server constraint, not a client constraint so should not change the client transport format.
Requiring a new Client request type to agree with a new Server endpoint type is just unnecessary and mixes up server versus client responsibility and interface design.
This is literally expressed in the document in section 1: Introduction. They just want to take that POST request and replace the word POST with QUERY which also means the server is intended to assure the request is idempotent instead of needing that documented out-of-band.
It focuses on a bit more on safety, which is why every mention of it the proposed method having the "idempotent" property is immediately preceded (in most cases in the same sentence) by description of it having the "safe" property.
The interpretation of a request is up to the server. There is no reason for the client to syntactically distinguish that the request body is for a POST vs QUERY; the request parameters and response have the same shape with the same serialization format.
However, on the other side, a server does control interpretation, so it is responsible for documenting and enforcing how it will interpret. QUERY semantics vs generic POST semantics is a receive/server-side decision and thus should not be a syntactic element of client requests, merely a server description of endpoint semantics (“QUERY endpoint” meaning shorthand for POST endpoint with query semantics).
edit: Thinking about it some more, there is one possible semantic difference which is that a transparent caching layer could use a syntactically different POST (i.e. QUERY) to know it should be allowed to cache the request-response. I do not know enough about caching layers to know how exactly they make fill/eviction choices to know if that is important.
The point is to have a standard, so you can more easily learn what an API is doing instead of having to start from scratch every time.