Wouldn’t just putting an etag on POST requests accomplish the same thing? If I’m understanding it the server has to maintain state to ensure idempotency.
If this is actually going to replace GET requests w/ query strings in the wild, Im very much hoping for browser bookmarks to support keeping request parameters.
Including a strong motivating example might have helped sell this, using an example that could trivially be expressed as a GET is extremely distracting.
Even imagining a QUERY with a large JSON filtering structure, or say an image input as request body, it feels extremely odd to include the request body as part of the cache key. It also implies an unbounded and user-controlled cache key, with the only really meaningful general caching strategy being bitwise compare of the request body (or a hash), which in a hostile scenario implies cache busting would be trivial.
This invokes multiple semantic oddities in one go with obvious difficulties for a very niche use case. If I'm writing a service that needs complex filtering or complex input like an image, any form of caching (e.g. individual data columns of a join, or embeddings keyed by perceptual hashes of a decoded image input) is going to be far away from the HTTP layer and certainly unrelated to the exact bit representation of the request on the wire.
Why even bother trying to capture this in a generic way?
I would be far more inclined to try and capture this caching semantic as a new header for POST. Something like "Vary: request-body" or similar. Perfectly backwards compatible and perfectly ignorable for all but the 0.1% of CDN use cases where the behaviour might turn out useful
One example - I'm building an MCP server at the moment for a database I'm working on. In ChatGPT I want to do dry-run posts first that roll back before committing - both are POST requests with a property - and it loves to trigger the safety layer in the tools (for various reasons, it's hard to debug exact causes)
But I think this would make it better - QUERY before POST means different request types, not just the same with a safety flag.
I like the proposal, but I agree they could have sold it better.
This is basically a GET request that can have a body. I've found myself in need of that more than once when I did not want huge URLs with encoded data showing up in logs. Using POST request there is not appropriate because it signals data could be modified (i.e. cannot be sent to read-only instances). I guess modifying the spec to allow GET to have a body would pose too many problems.
This is controlled by the (Last-Modified, If-Modified-Since) and (ETag, If-None-Match) header pairs. HTTP is stateless; it does not require any persistence. The only thing that defines kind of an optional persistence is the caching layer, for obvious reasons.
QUERY has existed in spirit for nearly two decades as WebDAV's SEARCH method https://www.rfc-editor.org/rfc/rfc5323 and the thing that always killed it in practice was intermediaries. Plenty of proxies, WAFs, and load balancers either strip the body from methods they do not recognize or reject the request outright, so the guarantee that sending a body is safe evaporates the moment traffic crosses a middlebox you do not control. Until gateway and CDN support is real rather than just on paper, POST with a header marking the body as part of the cache key stays the pragmatic choice.
I wonder if HTML forms will add support for QUERY:
<form action="..." method="query">
This would avoid the annoying re-submission warnings you're getting if you refresh a page that was returned by a POST form submission, since QUERY is required to be idempotent.
One oddity of forms: the result of a form POST is a page that has a location (the URL) but that cannot loaded via that location. As far as I know, the fact that the page is a POST and not a GET is not stored anywhere visible to the user or to JS. And refresh works oddly.
If method=QUERY were added, there would be a new variety of this weirdness.
Supporting more than GET/POST in HTML forms has been my dream for decades. There's a WHATWG proposal to do just that if you want to add your voice: https://github.com/whatwg/html/pull/11347
> GET request with a body was heavily considered by the IETF working group, but it was ultimately rejected in favor of creating the new QUERY method. The decision to create a distinct method came down to historical interoperability issues and strict compliance with the core architectural definitions of HTTP.
I've been sending request body along GET method for years now
It does seem like a boil-the-ocean "fix". The entire planet has been kludging this with GET or POST as appropriate for the entire lifetime of HTTP, and now there's a proposal to do something that looks identical to POST but with slightly different semantics? So in exchange for solving a problem that's been dealt with (if not perfectly) forever you'd need to convince the entire world to adopt a new, incompatible mechanism? I'll give this one as much of a chance as BEEP.
this was the response the last time this came up here.
you can do all kinds of nonstandard stuff if you control the server, the client, and any steps in between. the point of standards is for when you don't control it all.
put your server behind a managed load balancer or a caching proxy, and your get requests with bodies aren't going to do so well anymore.
I work with a custom own maded web framewrok for Java (from before Spring was a thing!). A funny thing it's that treats GET and POST petitons identical when try to recover parameters from the petitions. So GET and POST get parametertes from URL and from BODY. And this made some weird bugs many years ago, when in some case, we got repeated parameters in URL and BODY, trigering the framewrok to think that must put it on a List and pass it to the service method.
I don't hate it. Covers all the bases: 1.1, 2, 3/quic and solves real problems: get query limitations vs body content & post-without-mutation. Yes there are preexisting workarounds, but they're non-obvious.
As "just a guy that programs" (ok, now guides agents to program) and tries to follow the rules (with a big dose of pragmatism), this totally makes sense to me. This is also the first time I've seen or heard about this coming.
I like that we now have a way to not being forced to define Resources when we want to query. It always felt like I was missing something that there could be an infinite, defined-on-the-fly number of Resources for a "part" of a given Resource. Do I really want to define "all cats that sleep more than 20 hours a day and like sunbeams and want to eat breakfast at 3 am" as a Resource? (ok, we all know that is actually the full set of cats). I'm ok that you want to define that as a Resource but in my system, it makes more sense that Cats is the Resource and I just need some accepted way to query.
I like the implementation (again, as just a guy that programs). I don't see how it could have done it better or simpler which probably hides the complexity of getting there.
I also especially appreciate how the spec is written. Opening a spec, I wonder how far I'll get before I don't know what the heck they're talking about (and, again, as just a guy that programs). I don't think it's easy to write a spec that is complete and approachable like this. Really appreciate that.
The standards have always been a bit more abstract than you use in practice. Common practice prior to this would be /catsearch?sleep=20&sunbeams=yes&breakfast=0300 where the "resource" is /catsearch and the rest are query parameters, but you could also use /catsearch/sleep/20/sunbeams/yes/breakfast/0300 which looks like a "resource", but nobody is actually enforcing that it is a "resource".
I'll forever love a long, totally plain text document like this. So many good times with video game FAQs as a kid. It really is a superior form of information in a lot of ways (not all).
This whole thing is non sense. It basically mixes technical constraints (body or not body) with a functional requirement that arises from people that are tied to semantics of the protocol.
HTTP is transfer protocol. It should not ever imply anything at the business level.
Yes REST made it's worst mistake out if it by giving a meaning to the verb.
Yes proxies rule how the body is re-interpreted in spite of the will of the sender (wtf).
But the original RFC states clearly that any verb can be used. This is how WebDav normalised its own.
But playing fancy by introducing a change that all HTTP implementation will have to honor is a very bad and irrational choice.
I thought it wouldn't be a terrible idea to open up the GET method to contain a body but according to the original spec the GET body is to be ignored completely. There's also caching which would break because the important bit of the request would live in the stripped body.
Why not standardize a body in the GET request (which isn't forbidden per spec and works in many places already but isn't supported everywhere because it's not mandated to support it)?
Kinda pointless since traffic is encrypted. If you can terminate TLS you can apply any rule based on the content as well. Like headers which is more reliable.
61 comments
[ 5.1 ms ] story [ 72.5 ms ] threadEven imagining a QUERY with a large JSON filtering structure, or say an image input as request body, it feels extremely odd to include the request body as part of the cache key. It also implies an unbounded and user-controlled cache key, with the only really meaningful general caching strategy being bitwise compare of the request body (or a hash), which in a hostile scenario implies cache busting would be trivial.
This invokes multiple semantic oddities in one go with obvious difficulties for a very niche use case. If I'm writing a service that needs complex filtering or complex input like an image, any form of caching (e.g. individual data columns of a join, or embeddings keyed by perceptual hashes of a decoded image input) is going to be far away from the HTTP layer and certainly unrelated to the exact bit representation of the request on the wire.
Why even bother trying to capture this in a generic way?
I would be far more inclined to try and capture this caching semantic as a new header for POST. Something like "Vary: request-body" or similar. Perfectly backwards compatible and perfectly ignorable for all but the 0.1% of CDN use cases where the behaviour might turn out useful
But I think this would make it better - QUERY before POST means different request types, not just the same with a safety flag.
Exemple:
``` QUERY /search HTTP/1.1 Content-Type: application/json
{ "filters": { "region": "asia", "status": "active" }, "sort": "created_at", "limit": 500 } ```
can answer
``` HTTP/1.1 303 See Other Location: /queries/results/f3a9c1d7 ```
And then you can access later `/queries/results/f3a9c1d7` using a pure GET call, and cache this instead
This is basically a GET request that can have a body. I've found myself in need of that more than once when I did not want huge URLs with encoded data showing up in logs. Using POST request there is not appropriate because it signals data could be modified (i.e. cannot be sent to read-only instances). I guess modifying the spec to allow GET to have a body would pose too many problems.
If method=QUERY were added, there would be a new variety of this weirdness.
I've been sending request body along GET method for years now
Generally not a great idea. With some http implementations this is not even possible (for example, fetch)
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/U...
> You cannot include a body with GET requests
And transparent caching might result in weird issues.
You've never heard of BEEP? Well, that's why.
https://evertpot.com/get-request-bodies/
you can do all kinds of nonstandard stuff if you control the server, the client, and any steps in between. the point of standards is for when you don't control it all.
put your server behind a managed load balancer or a caching proxy, and your get requests with bodies aren't going to do so well anymore.
I think the name is confusing because the term 'query' is already used to refer to http requests in general.
Just the title of the RFC confused me.
In what circles is this the case? I sometimes colloquially refer to a GET request as a query, but definitely not so on a POST, PUT or DELETE.
Edit: ah, they declare QUERY as "safe" meaning no side effects, for cacheability. My mistake.
I like that we now have a way to not being forced to define Resources when we want to query. It always felt like I was missing something that there could be an infinite, defined-on-the-fly number of Resources for a "part" of a given Resource. Do I really want to define "all cats that sleep more than 20 hours a day and like sunbeams and want to eat breakfast at 3 am" as a Resource? (ok, we all know that is actually the full set of cats). I'm ok that you want to define that as a Resource but in my system, it makes more sense that Cats is the Resource and I just need some accepted way to query.
I like the implementation (again, as just a guy that programs). I don't see how it could have done it better or simpler which probably hides the complexity of getting there.
I also especially appreciate how the spec is written. Opening a spec, I wonder how far I'll get before I don't know what the heck they're talking about (and, again, as just a guy that programs). I don't think it's easy to write a spec that is complete and approachable like this. Really appreciate that.
I’ve enjoyed the combination with Range headers for paging, despite this tidbit:
> It is expected that these built-in features will be used instead of HTTP Range Requests
Using the QUERY request as the definition of a set, and Range to retrieve subsets seems very natural.
https://www.rfc-editor.org/rfc/rfc10008.txt
HTTP is transfer protocol. It should not ever imply anything at the business level.
Yes REST made it's worst mistake out if it by giving a meaning to the verb.
Yes proxies rule how the body is re-interpreted in spite of the will of the sender (wtf).
But the original RFC states clearly that any verb can be used. This is how WebDav normalised its own.
But playing fancy by introducing a change that all HTTP implementation will have to honor is a very bad and irrational choice.
I thought it wouldn't be a terrible idea to open up the GET method to contain a body but according to the original spec the GET body is to be ignored completely. There's also caching which would break because the important bit of the request would live in the stripped body.