RFC 10008: The new HTTP Query Method (rfc-editor.org)

202 points by schappim 7 hours ago

100ms 5 hours ago

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

Joker_vD 5 hours ago

> It also implies an unbounded and user-controlled cache key,

The query part of GET's URI is also barely bounded in practice and user-controlled, and is indeed used as part of the cache key (because it's a part of URI), so I am not sure why you raise this objection at all.

giancarlostoro 5 hours ago

> and user-controlled

I've found some sites that tack on a session ID and if you try to tamper with the URL in any way, it sends you back to "Page 1" really annoys me lol at that point let me skip to any page with your web UI.

PunchyHamster 4 hours ago

Well, because it is more code. Current caching software caches by headers + query string. It now needs to be expaned to cache by body too.

It feels very pointless and there is no drawback of just using POST

OvervCW 3 hours ago

afavour 3 hours ago

CodesInChaos 5 hours ago

The browser can simply store a collision resistant hash (e.g. SHA-256) of the body, if it wants a smaller cache key. I can't really think of any caching related attacks that don't equally apply to a query parameter. Generating a unique 30 character query parameter is just as easy as generating a 30 MB request body, if you want to flood the cache.

ralferoo 3 hours ago

Not necessarily that simple, as you'd have sort all the input parameters to maintain a useable cache key. Not especially difficult, but if the data is large and so re-allocation and sorting is required, then you're starting to open up the attack surface where bugs might have been introduced.

tanepiper 2 hours ago

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.

cryptonym 5 hours ago

Sure you can provide an image as request body, but you could already do it with b64 query parameter. If you try hard enough, you can poorly use any proposed standard. GET with query parameters already is opaque and makes cache busting trivial.

layer8 5 hours ago

Query parameters are length-limited, because HTTP URIs are: https://www.rfc-editor.org/info/rfc9110/#section-4.1-5. There is no expectation for arbitrarily long HTTP URLs to be functioning.

cryptonym 4 hours ago

inigyou 3 hours ago

Not all usage scenarios are the public internet, and something doesn't have to be useful on the public internet to be standardized.

Realistically, systems for the public internet will use a secure hash as the cache key so it'll always be the same size. The cache key already includes a URL that can be very long, and an arbitrary set of header values.

ralferoo 3 hours ago

Except that by definition, in a URL the data has no implicit meaning so for a cache hit you need an exact match, including order and case, but for a list of POST parameters, they could legitimately be in any order and so you can't just hash it all as a blob, you need to sort the keys, possibly copy data around (unless using keys plus hash), probably allocating more memory, etc. I'm pretty certain we'll see at least one CVE out of the first few implementations of this!

inigyou 2 hours ago

epolanski 5 hours ago

> Why even bother trying to capture this in a generic way?

I guess it's about resolving the odd semantics of using POST which is not idempotent and thus allowing easier control flow of caches and retrys.

Your perspective is 100% correct if you think at the application-layer, but with a dedicated method, you can have that behaviour out-of-the-box out of your HTTP infrastructure (whether it's at your hyperscaler's router or your apache/nginx/browser whatever) and stop implementing yourself the post-as-a-query edge case.

friendzis 5 hours ago

> It also implies an unbounded and user-controlled cache key.

While the concern is valid, caching is entirely optional at query level, therefore it is totally valid to cache only certain "filters".

davidkwast 5 hours ago

I would use a hash of the body content (the query) as a URL parameter

/?hash=123456789

Joker_vD 5 hours ago

Why? That's pushing more work to do both on yourself and the cache.

wang_li 4 hours ago

If you control the full stack then the functionality described here can be implemented with POST. The only way this comes into play is if some second party client of your service is trying to impose rules on how your backend works. My answer to that is no. I will be defining the contract by which my services operate.

CodesInChaos 5 hours ago

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.

chrismorgan 19 minutes ago

acabal 43 minutes ago

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

bob1029 4 hours ago

This is better solved with the post redirect get pattern.

diroussel 38 minutes ago

That is the good old fashion workaround. But why is it better than a form causing an HTTP QUERY.

If we can do QUERY forms, it would be an ideal time to add JSON encoding for forms.

amluto 3 hours ago

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.

sheept 2 hours ago

At least browsers wouldn't have to warn users that they'd be resubmitting data if they reload the page after submitting a query form, since query requests are intended to be idempotent

amluto 2 hours ago

tempfile 4 hours ago

Depends whether your form submission should expect side effects or not. Most forms submissions have side effects. If the effect is truly idempotent, wouldn't PUT be a better verb? That is also supposed to be idempotent.

diroussel 35 minutes ago

GET and QUERY are both idempotent.

echoangle 3 hours ago

You can’t use PUT as a form action though.

100ms 5 hours ago

Forms, HTTP implementations, public API surfaces, and all for what exactly. Introducing a new verb for this feels profoundly misplaced

jagged-chisel 5 hours ago

Idempotency is an important attribute for correctness. Yep, you can document that POSTing to $ENDPOINT is idempotent, but you can't communicate that to caching layers throughout the network. QUERY, by definition, is idempotent and cacheable.

resters an hour ago

jnewton_dev 4 hours ago

alpinisme 5 hours ago

At least support - or lack thereof - for a new verb is unambiguous (compared to changing the semantics of GET)

ctdinjeu7 5 hours ago

Now HN’s UX can finally be decent.

The team will have to wait for a new header and textarea specs to fix the rest of the jank.

This site is so awful lol. Why don’t they update it?

CodesInChaos 5 hours ago

Where does HN use POST for safe operations? I can't think of any.

Comment submission isn't safe, so QUERY can't be used there. And it doesn't suffer from the problem anyways, since HN returns a 3XX on successful submission, so refreshing doesn't show a warning.

ynac 3 hours ago

Just in case anyone wants to pretend it's still that other century:

https://www.rfc-editor.org/rfc/rfc10008.txt

jjice 3 hours ago

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).

riffic 3 hours ago

I have a thesis brewing that explores how rich text WYSIWYG editors create a "what you see is all there is" cognitive bias, while plain text overcomes it.

riffic 3 hours ago

beautiful formatting. I should crib this style template for internal work memos, it's timeless.

piterrro 4 hours ago

> 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

huskyr 4 hours ago

Apparently some load balancers drop the body.

inigyou 3 hours ago

I expect all sorts of intermediaries may drop the body, since having a body is forbidden by the standard.

When it's your client talking to your server you can obviously do whatever you want - it doesn't cause problems until you want to involve third-party code, such as a reverse proxy (such as nginx) or a CDN. This includes proxies your customers may be using.

preisschild 3 hours ago

> 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.

barbazoo an hour ago

> GET: Content (body) "no defined semantics"

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.

stymaar an hour ago

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)?

mholt 4 minutes ago

Too many servers ignore/drop/reject body in GET requests. RFC 9110 does allow it, but is only recommended if server documentation states that it is supported.

simon84 an hour ago

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.

drob518 16 minutes ago

Aside: Wow, we’ve hit 5-digit RFC numbers now!

andltsemi3 6 hours ago

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.

inigyou 6 hours ago

Probably won't. Probably will replace whenever POST is currently used for a query.

pwdisswordfishq 6 hours ago

Wait, it's already past 10 thousand?

rhplus 5 hours ago

Someone has an ambiguous bet predicting when RFC 10000 will be published, but the numbers went straight from 9998 to 10008. No-one wins!

https://manifold.markets/CollectedOverSpread/when-will-rfc-1...

ekr____ 4 hours ago

RFC 10000 will not be published. They're just going to skip past the number.

https://mailarchive.ietf.org/arch/msg/tools-discuss/EpoQcVt_...

RFC #s are issued sometime before publication, so they can come out out of order. I would expect 9999, 10001, etc. to show up eventually.

echoangle 3 hours ago

> This question resolves to the month of publication of the lowest-numbered RFC with a number greater than or equal to 10000.

So of 10008 is the first one after 10000, that date is the one to bet on.

Imustaskforhelp 5 hours ago

Everytime I think that prediction markets bets can't get worse, they do, all in weird ways. I never expected someone betting over when RFC 10,000 will be published but somehow its fits just about right for prediction markets.

just wow, people seem to be having too much money it seems for them to bet over when RFC's are gonna get released.

This isn't even one of the worst offenders on prediction market or even comparable to it but I am just amazed (in a negative manner, surprised? its just strange) by the depth on what people actually bet on these markets.

networked 5 hours ago

etchalon 7 minutes ago

Why does this feel like GraphQL demanding everyone else solve their problems?

tonympls 4 hours ago

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.

inigyou 3 hours ago

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".

smashed 4 hours ago

Use the QUERY method in your http query to query search results. Do not add query parameters.

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.

comfydragon 2 hours ago

> the term 'query' is already used to refer to http requests in general

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.

jbmchuck 5 minutes ago

I'm guessing the op is referring to https://en.wikipedia.org/wiki/Query_string

mlhpdx 4 hours ago

Wow, it still isn’t a standard? I’ve been building with the QUERY method for years now.

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.

toybeaver 6 hours ago

This makes me happy tbh, I was never a fan of creating `POST /search` endpoints when working with robust APIs

CodeWriter23 35 minutes ago

It's about time.

AtNightWeCode 35 minutes ago

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.

cosmotic 2 hours ago

Why not just define the semantics of a GET request body?

advisedwang 2 hours ago

There's countless proxies in the wild that would not behave correctly with an RFC-defined GET-with-body, and there's no way for a client to know if that's the case.

QUERY has the advantage of getting default behaviour from most proxies (which at least is well behaved even if inefficient). If there are any proxies that just drop QUERY requests, at least they won't silently mangle the request.

This is the same way that instead of improving how HTTP 301 was specified, HTTP 308 was created. It's a pragmatic move.

chadgpt3 2 hours ago

Proxies often delete it

elAhmo 2 hours ago

They could be updated to not delete it, like they would require for this new method anyway.

moralestapia 2 hours ago

brookst 6 hours ago

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.

CodesInChaos 6 hours ago

QUERY is GET with a request body. So it must be safe, not just idempotent. Where safe means it has no significant side-effects. Typically servers will not keep any state for QUERY requests.

There is one interesting variant though, which uses state: The client sends a QUERY containing the full query, and the server returns a url usable with GET with which this query can be triggered in the future. Similar to prepared statements in SQL databases.

Using QUERY for GraphQL queries (not mutations) would be a good match. These only read data, but are sometimes bigger than the url length limit.

brookst 5 hours ago

Thanks for the explanation!

I still don’t get how idempotency can typically be ensured without state. It very much depends on data model and application design. Even side effects like using a user’s lookup quota need to be handled at a higher layer than HTTP (I think?).

wongarsu 4 hours ago

inigyou 3 hours ago

Joker_vD 5 hours ago

CodesInChaos 4 hours ago

trollbridge 6 hours ago

Ideally, libraries like FastAPI, etc. could be configured to translate QUERYs to GETs, until you can rewrite your code to automatically support both.

n_e 5 hours ago

Interestingly, despite the QUERY request being safe, the RFC says it's subject to preflight requests:

> A QUERY request from user agents implementing Cross-Origin Resource Sharing (CORS) will require a "preflight" request, as QUERY does not belong to the set of CORS-safelisted methods (see [FETCH]).

CodesInChaos 5 hours ago

Joker_vD 5 hours ago

    Unlike POST, however, the method is explicitly safe and idempotent, allowing
    functions like caching and automatic retries to operate.
Essentially, it's for things that are inherently safe/idempotent already (e.g. search or indeed, anything that you don't mind being retried) but require a lot of data passed in the request.

nottorp 5 hours ago

It's as bookmarkable as a query with its parameters in the POST data...

geth101 2 hours ago

Just allow body for get. Problem solved.

CodeWriter23 31 minutes ago

Nah, you need the 405 Method Not Allowed to be returned by legacy systems and proxies along the way to your bleeding edge server rather than silently failing whilst dropping the params in the request body.

lanycrost 6 hours ago

query strings always had size limit, seems this new type will solve it which will be really good.

drzaiusx11 4 hours ago

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.

haeseong 5 hours ago

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.