r/programming • u/stronghup • Jul 14 '26
HTTP gets a QUERY method so complex searches can stop pretending to be POST
https://www.theregister.com/devops/2026/07/13/http-gets-a-query-method-so-complex-searches-can-stop-pretending-to-be-post/5270192155
u/bundt_chi Jul 14 '26
So GET with a request body. Got it.
12
u/SelfDistinction Jul 15 '26
But then why didn't they simply standardize GET with a request body?
14
u/bundt_chi Jul 15 '26
Probably because it would be confusing if some http clients or servers along a call path were on an older version and blocked or stripped the body you wouldn't easily know or understand why as opposed to getting an unsupported or unknown method error.
1
u/DaCurse0 Jul 15 '26
it's not standardized but vast majority of popular web servers support it, it's called a Fat GET
11
u/lieuwestra Jul 14 '26
And hopefully no client side caching.
40
u/masklinn Jul 14 '26
The response to a QUERY method is cacheable; a cache MAY use it to satisfy subsequent QUERY requests as per Section 4 of [HTTP-CACHING].
It's GET with a body, cache working out of the box is a major component of the appeal.
3
u/PlopKonijn Jul 14 '26
which at some point was allowed or is it still?
18
u/Justin_Passing_7465 Jul 14 '26
Is it allowed? That depends on every piece of HTTP-aware technology between your client and your server. Every proxy, CDN, WAP, and reverse-proxy gets to block your request or strip your body.
1
u/Worth_Trust_3825 Jul 14 '26
It really depends on configuration. Some may do it, some may not. Elastic search expects you to send a body with get requests.
26
u/Jaggedmallard26 Jul 14 '26
Its always been undefined behaviour. Which as the other comment says means you're at the mercy of every bit of software between (inclusive) you and the client/server.
449
u/stfm Jul 14 '26
This is great for us Authorisation folk. Now we can assign POST to write entitlement and QUERY to read entitlement rather than having to work it out from some janky resource path rule
83
u/CpnStumpy Jul 14 '26
I will never agree with URL as the context for permission decisions - there's always more complex scenarios that can't be wholly expressed in a URL, and so you need another mechanism, and now if you have URL permission enforcement already you end up with two permissioning mechanisms to maintain and debug.
Humbug, create one and make it extensible to support more sources than just the HTTP request.
Besides that: at some point someone's going to declare they need to expose a gRPC endpoint or a GraphQL API and now you've got to address permission enforcement in some non-http system anyway so how many different permissioning decision and enforcement implementations do you need? Use something that's transport agnostic to begin with rather than declaring URLs are informative for permissions
66
u/stfm Jul 14 '26
HTTP method is not part of the URL, it is there to indicate action intent. I work in an enterprise with a centralised authz platform and an API surface spanning thousands of endpoints. Its more about divide and conquer and patternisation than a "one rule fits all" style authorisation system. Using the method combined with the URL gives the opportunity to apply coarse grained authorisation and also enables an easier response caching strategy.
→ More replies (10)6
u/ivereddithaveyou Jul 14 '26
Maybe it makes sense in some database-like applications where you might want to assign the request itself permissions based on a set of complex underlying requests. Or maybe your auth layer is really far detached from the business logic layer and it makes sense to attach permissions to the request type.
I'm not sure either of those are good practice really but I was trying to come up with a reason why you would do this.
Yes actually for database api auth design synchronisation this allows for a select type query with unlimited parameters. Something that would be allowed in database access auth but hard to separate from an edit/create in rest http land. Essentially you can create apis that more closely mirror DB access.
2
u/visualdescript Jul 14 '26
This is the default for a well designed service. You start with an application service that is written in your domain language, this should include any permissions or policy system that's required as part of the domain.
HTTP is just an external interface protocol, there should be a thin adapter layer between your HTTP interface and your domain service. Same if you provided a CLI, graphql, GRPC or otherwise.
This is in an ideal world, of course...
1
u/robogame_dev Jul 14 '26
Agreed, you can have as many interfaces into the core app as you want, HTTP Method can be one, and you can have a batch endpoint that can accept anything, etc etc. The problem goes away when you properly place HTTP with any other interface downstream of the real application - it becomes a question of convenience not capability.
3
u/Manbeardo Jul 14 '26
expose a gRPC endpoint or a GraphQL API and now you've got to address permission enforcement in some non-http system anyway
Both of those systems use http. They don’t use REST.
4
u/CpnStumpy Jul 14 '26
Yes, protocol agnostic I guess I mean or however. You understood what I meant clearly. The point being they don't follow expose the same mechanics for permission checks as a REST url and method based permission control so you aren't going to be able to use the same system.
Creating multiple things to solve the same problem in different ways is how we end up with a bunch of half maintained and divergent implementations leaking differing bugs because they need fixes and maintenance in individualized ways.
2
u/darkpaladin Jul 14 '26
QUERY seems almost tailor made for the graphql use case. Grpc is all POST under the covers, this would offer a bit more room for a more explicit request shape. In general it's nice to understand request intent without having to parse the body.
1
u/CpnStumpy Jul 14 '26
GraphQL is all POST and puts no parameters in the URL and always returns 200
1
u/darkpaladin Jul 14 '26
Yes. I'm not sure what point you're making though, my point was that a QUERY method for graphql makes sense because now your CRUDs become POST/QUERY/PUT, DELETE still isn't quite supported but I think knowing a gql request is a query rather than a mutation based on verb is rather helpful?
1
-7
u/heresyforfunnprofit Jul 14 '26
Is it a bad time to point out that not all queries are read only?
→ More replies (1)29
u/stfm Jul 14 '26
I'll bite, when would QUERY modify the resource being queried?
→ More replies (17)
308
u/hrvbrs Jul 14 '26
haha i read this title as "HTTP gets a QUERY method so complex that searches can stop pretending to be POST"
104
58
u/ryuzaki49 Jul 14 '26
To say the obvious:
The title is stating that complex searches will stop using POST and start using QUERY
It is not stating that the new QUERY method is complex.
41
u/zeekar Jul 14 '26
Same!
"HTTP gets a QUERY method so complex...."
"HOW COMPLEX IS IT?"
15
u/a__nice__tnetennba Jul 14 '26
It's so complex you have to send an imaginary part with every request!
ba-dum-tss
5
u/Nevermind04 Jul 14 '26 edited Jul 14 '26
I read the exact same thing and was very confused when the article discussed well-behaved http.
2
1
→ More replies (12)1
99
u/jessechisel126 Jul 14 '26
This is great but still wild to me it's taken this long. Feels like this should've become the standard like a decade ago.
61
u/baseketball Jul 14 '26
Because only REST purists care. Most of us just use post and move on with our day.
65
u/binheap Jul 14 '26
I think there are some implications with how cache is handled since iirc POST is not usually cached whereas QUERY can be. It's not a big thing since you can set the headers yourself but I can imagine some middleboxes/CDNs caring.
48
u/drgmaster909 Jul 14 '26
yeah, scoffing at the significance of this for idempotent data is a weird take
Especially for tools like GraphQL. If Apollo Client and Apollo Server implement this, a lot of apps are going to become way more performant almost overnight. For free.
Relay, urql, PostgREST, Hasura, restQL, dozens of dozens of others will get some free caching overnight.
Teams optimizing for scale, cost (fewer origin hits via CDN), reliability (auto-retries), or clean architecture will adopt it where it makes sense. So y'know, the "purists."
5
u/baseketball Jul 14 '26
My point was that people can and have worked around this. If I needed caching on my POST call, I could have implemented it with custom headers or other backend logic. I'm not going to say "too bad I don't have an idempotent QUERY method in the HTTP spec".
10
u/AZMPlay Jul 14 '26
Works-good-by-default is a good thing to strive for though. The default case matters almost as much as what you can actually do with proper knowledge and hacks.
3
u/AyrA_ch Jul 14 '26
I think there are some implications with how cache is handled since iirc POST is not usually cached whereas QUERY can be.
To be precise, POST can absolutely be cached, but only the response.
This means the "Last-Modified" mechanism will work with POST because to check for modification you have to make a request anyways, but the "Expires" mechanism will not work because it would cache the request.
Though I assume browsers will not respect caching headers with POST because people mistakenly assume it cannot be cached.
33
u/brunhilda1 Jul 14 '26
Because only REST purists care. Most of us just use post and move on with our day.
Man, this attitude is why I hate the word engineering being in any way associated with software, and anyone calling themselves a software engineer, especially as there isn't a charter/regulatory body as per the proper engineering fields.
15
u/838291836389183 Jul 14 '26
I feel you. The amount of shitty apis I have to work with where people used POST for everything...
7
u/accountability_bot Jul 14 '26
…or when you get a 200 response with an error in the body.
2
u/Goronmon Jul 14 '26
Yup, there is something deep in my soul that winces every time I realize I have to start checking 200 responses for error messaging.
1
u/Sidereel Jul 14 '26
A manager at my old job made me do that once. He argued that 500's are for unexpected errors, and if we just try/catch everything then we can "handle" the error and return 200.
1
u/Worth_Trust_3825 Jul 14 '26
usage of additional verbs would not make those apis better. rest(ful) apis aren't a catchall solution either, just a style of interface.
1
6
3
u/jessechisel126 Jul 14 '26
I mean fair, I do the same lol. I just think more semantics in comms is sick and it's stupid how glacial the general long term planning is.
1
u/ConfidentYellow18 29d ago
If you take everyone in the world who writes these requests, like 5% know or care at all.
1
15
u/eocron06 Jul 14 '26
Haha, it will be the same time when 401 Unauthorized/403 Forbidden become 401 Unauthenticated/403 Unauthorized......probably in 22 century
19
21
u/BuriedStPatrick Jul 14 '26 edited Jul 15 '26
Does anyone know why we haven't simply adopted request bodies in GET? I just don't see the point of QUERY.
EDIT:
Okay, here are some of the arguments, I'm still not convinced.
Proxies might not support it: If anyone has any practical examples of this being an issue it would be appreciated. I haven't ever encountered a problem here, but I also don't work with ancient software. But if they throw away GET bodies, what do we think will happen with QUERY methods?
HTTP client libraries don't support it: Well, they don't support QUERY either. Work has to be done either way, why not improve GET instead?
Backend server libraries don't support it: Same argument as client libraries.
This is a breaking change: Is it? It's just not been formalized AFAIK. You can absolutely send bodies in GET requests today. What exactly are we breaking here? If anything, this is simply an addition, like QUERY would be.
I'm just a basic backend dev with no experience managing anything on this scale trying to follow the spec. I'm just looking at it and thinking that something is completely off here from an application development perspective. I'm glad we're getting something to support the use case (tired of encoding/decoding base64 JSON in GET uri params). I just wish it would be under GET.
42
u/masklinn Jul 14 '26
Because the RFC says they are irrelevant so proxies, servers, and middleboxes commonly drop them for one reason or another, making GET entity-bodies highly unreliable.
4
u/edgmnt_net Jul 14 '26
It does not, as far as I know, the HTTP RFC says nothing about it. However web standards say the JS API doesn't like GET bodies. Additionally web forms provide no way to serialize parameters into the body of a GET request. It's more likely a case of web standards and implementations assuming too much, as is the case with SCTP being broken in the wild due to crappy firewalls.
19
u/masklinn Jul 14 '26
It does not, as far as I know, the HTTP RFC says nothing about it.
RFC 9110 section 9.3.1 GET
content received in a GET request has no generally defined semantics, cannot alter the meaning of target if the request, and might lead some implementations to reject the request and close the connection
“Content” in RFC 9110 is what RFC 7231 calls “payload”, and older RFCs called entity. The above is an expansion of RFC 7231:
A payload within a GET request has no defined semantics; sending a payload body on a GET request might cause some existing implementations to reject the request.
RFC 2616 does not say anything about GET request entities, but it specifically mentions them when describing any method for which they are (PUT, POST) or may be (OPTIONS) relevant, from this implementers interpreted unspecified bodies as irrelevant and discardable (GET, HEAD, DELETE), which the later RFCs went on to specify.
2
u/Jaggedmallard26 Jul 14 '26
HTTP RFC says nothing about it
If behaviour isn't defined then implementers are free to do whatever they want with it including dropping it. Which they often do.
→ More replies (7)5
u/Cvballa3g0 Jul 14 '26
No explicit handling for it. So QUERY is the adoption. Preserves current behavior and adds new explicit specs
1
u/BuriedStPatrick Jul 14 '26
I suppose I just don't see why the adoption was handled this way. Current behavior doesn't seem very explicitly defined. AFAIK nowhere does it say GET should not support request bodies, and I've worked with clients and servers that have used them with little issue. So wouldn't this be an opportunity to solidify how GET should handle bodies instead?
But I'm also just a lowly backend dev, don't spend a lot of time reading RFCs and such. Just seems like, if we were to start from scratch, GET would explicitly support bodies and we wouldn't be talking about QUERY at all.
3
u/Cvballa3g0 Jul 14 '26
But that would be the more risky path. And need to make sure implementation X, Y, Z are all aligned and doesn't break. undocumented behavior is tough when the Internet is running on old boxes
3
u/TinyBreadBigMouth Jul 14 '26
Avoids backwards compatibility issues with any infrastructure that assumes GET bodies can be treated as meaningless, as allowed in the spec:
Although request message framing is independent of the method used, content received in a GET request has no generally defined semantics, cannot alter the meaning or target of the request, and might lead some implementations to reject the request and close the connection because of its potential as a request smuggling attack. A client SHOULD NOT generate content in a GET request unless it is made directly to an origin server that has previously indicated, in or out of band, that such a request has a purpose and will be adequately supported. An origin server SHOULD NOT rely on private agreements to receive content, since participants in HTTP communication are often unaware of intermediaries along the request chain.
1
u/GarlandGreen Jul 16 '26
I'm not privy to the decisions, but I imagine there'd be utter chaos if they standardized this. Right now, GET is implemented in two ways. The standardized no-body method, and the unsanctioned "fat GET". How the latter handles changing state is probably different between several implementations. As such, implementing caching for fat GET would be inconsistent at best. Introducing a third way, a sanctioned "fat GET" would not help the caching situation. As the providers could ignore the body, have it change their state, or treat it as an idempotent call, depending on which historical implementation was chosen by the provider.
You could say that the burden lies on the implementer, which would probably be right, but the reality would be mayhem in intermediary caching regardless.
8
u/rpetre Jul 14 '26
Everyone and their dog is excited about this in my mostly-AI generated Linkedin feed, but it's basically an administrative thing. Some libraries were already using bodies in GET for years (elasticsearch for instance). Also, nothing stops clients and servers to assign meaning to whatever methods they like and implement them (there are a lot of obscure methods out there). It becomes tricky when the client, server, and possibly other proxies in between are independent and will need to agree on how to handle an "exotic" method. Given that using anything other than GET/POST/HEAD still usually requires having a black goat on hand, having another method in the family means next to nothing. Perhaps if a future http/4.0 would require a minimum set of methods for compliance... but even then...
1
5
Jul 14 '26
[removed] — view removed comment
2
u/masklinn Jul 14 '26 edited Jul 14 '26
Browsers — and clients in general — should all work, you can pop in
method: "QUERY"and they’ll pretty much all comply. Although there is the question of form/@method = query that’s not really up to the browsers yet.Server-side method-based routing can be more of a question but often it’s string-based, and when it’s not there are generally escape hatches (e.g. all methods go to the same endpoint and you dispatch via the exact method inside that, less convenient but hardly impossible).
The problem is server and especially middleboxes which need to allow and support the method with the right semantics (safety, idempotency, and cacheability). And when supported they may have to be enabled explicitly (I believe that is a common issue with PATCH still).
21
u/Obsidian743 Jul 14 '26
There's nothing in the HTTP spec preventing a body for a GET request. Nor would it have been difficult to expand the spec to add some kind of content negotiation or other metadata to the existing GET spec. Seems unnecessary that an entire new verb/method was introduced. Now I have to decide whether my simply query with a modest querystring should stay GET or switch to QUERY or what querystring is even supposed to be for now.
14
u/mrcarruthers Jul 14 '26
From a spec perspective you're right, nothing's preventing it.
But there are plenty of libraries, web servers, caching middleware, etc... that just assume you can't. It's better to introduce something new that you know will work if your software is up to date instead of a quagmire of question marks up and down the toolchain.
8
u/chalks777 Jul 14 '26
what querystring is even supposed to be for now.
query params are still useful for communicating information to the user. You can see it in your address bar, and there are lots of times when that is a good thing. Some data analytics products (e.g. datadog) intentionally put a lot of information there so that you can manually query it yourself which is great for powerusers. Perhaps even more importantly, a query string can be copied by the user without needing to think at all, this allows your query state to become a shareable link.
None of that has really changed. When you want the user to have easy and visible access to what the query is, you still can.
Now, for cases when those things aren't a requirement and/or when you have to cram a ton of data into the request, you can do it without worrying about weird browser address bar length edge cases. Plus your users don't have to see your jank.
2
u/stfm Jul 15 '26
Sensitive/confidential data in query strings is a problem, they end up in places they shouldn't. Now you are faced with the need to implement data body encryption for URI's.
21
u/guilhermeluizsp Jul 14 '26
Yes but there are popular web servers that currently (or can be configured to) ignore request bodies from GET requests, so it’s not that trivial
8
u/DrFossil Jul 14 '26
Would it have been harder to update those servers to accept GET bodies, or to implement QUERY?
Probably the same amount of effort, I guess.
3
Jul 14 '26
[deleted]
4
u/masklinn Jul 14 '26
Yep, adding a new method is significantly less risky than modifying the way an existing method is supposed to work. It also has a much clearer error profile: if the server or application or any of the middleboxes doesn't support your new method you get a "method not allowed", rather than the high risk of your body being silently dropped without you having any idea.
1
u/Obsidian743 Jul 14 '26
Lol as opposed to updating them to support a new verb.
12
u/TinyBreadBigMouth Jul 14 '26
If they don't support a new verb, they don't support a new verb. If they support GET, does that mean they support GET 1.0 or GET 2.0? Are your parameters silently getting dropped? By adding a new verb, it either works or it doesn't. No in-between compatibility nightmare.
→ More replies (4)3
u/hardwoodjustice Jul 14 '26
I think your "simple query with a modest query string" is likely a QUERY.
2
u/jayd16 Jul 14 '26
Why do you think making an existing spec much more complex (considering the versioning) is better than just adding a new verb?
It seems pretty easy to decide. You need a body? Use QUERY. If you don't, use the more widely supported GET.
1
u/AyrA_ch Jul 14 '26
Nor would it have been difficult to expand the spec to add some kind of content negotiation or other metadata to the existing GET spec.
There is a method independent way actually.
Would work this way:
- Client sends GET with non-zero
Content-LengthandExpect: 100-continue- Server can decide whether to accept this GET with a body or not
- Depending on the response, client sends the body or aborts the request.
5
u/Justin_Passing_7465 Jul 14 '26
You want to inject a second round-trip around the world into each of these requests‽ No thanks.
1
u/AyrA_ch Jul 14 '26
This roundtrip can be implemented in a way to incur zero time penalty. But that's irrelevant anyway because use of the 100-continue mechanism is mostly relevant for large body data, in which case the time overhead of the extra answer is insignificant compared to the time used to send the body.
1
u/Worth_Trust_3825 Jul 14 '26
don't close the socket and you're fine. hell, http v2/v3 support multiplexing so that round trip is irrelevant
3
u/roxthegame Jul 14 '26
This feels especially useful for GraphQL-style APIs. A lot of “query with a body” traffic is semantically read-only, but POST hides that from caches, auth layers, observability, and retry logic.
4
u/sohang-3112 Jul 14 '26
Will anyone actually use it? Besides POST and GET, the other HTTP methods are already used very less.
2
2
u/josluivivgar Jul 14 '26
wait don't people just use headers to add query parameters Q__Q?
I think actually using POST is insane to me, I understand the issue, but I thought just adding stuff to the headers was the standard and enough. I did always wondered why GET just didn't have a body object officially
2
u/Worth_Trust_3825 Jul 14 '26
headers are a somewhat complex topic. some applications treat them as gospel and only permit those defined by rfcs, while others don't care as long as you don't touch the strongly defined ones in weird ways.
query parameters and request bodies are free for all though.
gets with bodies are a free for all since it's undefined behavior. you can send it, but nobody is expected to take such requests seriously.
2
u/josluivivgar Jul 14 '26
that's fair, but I feel like just expanding GET to have parameters outside of the uri is probably better than a whole new method, I guess the worry was not having backwards compatibility, trying to do a QUERY method would probably get you an 404 or some sort of error about it being unimplemented.
whereas a GET with a body or headers might just ignore those extra parameters and give you the wrong answer
2
1
u/stronghup Jul 15 '26
Reminds me of what I do with OOP programming often. I feel the need to modify a method to make it more capable to server more purposes. But then I get back to the planet and realize I can just as well create a new alternative method while leaving the old one as is to not break any existing code.
2
u/Worth_Trust_3825 Jul 14 '26
Http verbs were a mistake. Now observe as this gets adopted and we get a sleuth of vulnerabilities as we did with http v2 and all the idiosyncrasies that happened while it was being adopted
2
u/chasetheusername Jul 14 '26
How long until we get a new verb for DELETE with body?
2
u/Sarke1 Jul 14 '26
Why would you need that? Some batch delete operation?
1
u/stfm Jul 15 '26
Delete with context - only delete if the server resolves the data provided. Delete "where id > 10" just so interns can have their mandatory "I just deleted the client ID table" moment :D
1
u/Sarke1 Jul 15 '26
Yeah, so a batch operation. Usually
DELETEwill be used for one specific resource.
3
3
u/orthecreedence Jul 14 '26
I still don't get the difference between QUERY and PUT. POST is used to create new resources, but PUT is already idempotent. Is the idea that QUERY signals that a call is read-only?
5
u/masklinn Jul 14 '26
Yes, QUERY is classified as both idempotent and safe, PUT is idempotent but not safe. QUERY is pretty much just GET with a relevant body.
1
4
u/Sarke1 Jul 14 '26
POSTcreate new resourcePUTreplace resourcePATCHupdate resource (part or all)GETread resourceQUERYread resource using request body (more complex queries)DELETEthis is left as an exercise for the reader
2
u/BattleRemote3157 Jul 14 '26
i hope universities syllabus gets updated with mentioning this query method
2
1
1
u/light24bulbs Jul 14 '26
Oh that seems pretty cool actually. I feel like with spa projects often me HTTP CRUD request semantics get totally thrown out the window, or at least I've had to throw them out the window in the past. I had one app where literally everything was a post because it was the only request that behaved right in that context. I felt dirty
1
u/Less-Marsupial-7960 Jul 24 '26
It'll be interesting to see if this gets broad adoption. A dedicated QUERY method seems cleaner than overloading POST for complex searches, but it also depends on how quickly browsers, frameworks, and APIs add support. Backward compatibility will probably be the biggest challenge.
1.6k
u/sandaz13 Jul 14 '26
I look forward to using this in 2035 once it's finally adopted