News for hackers. Stuff that matters.
Re:Request bodies in GET requests by dillondoyle on Monday January 31, 2022 @02:48PM (#30153246)
genuinely curious. why? Does it make a big difference in your code or user experience?
Re:Request bodies in GET requests by tptacek on Monday January 31, 2022 @03:27PM (#30153793)
Yes! It can make a big difference! For instance: in a single-writer many-read-replica deployment, GETs might be routed automatically to replicas, while POSTs might have to be routed to the writer. You can design around it (for instance, route everything to replicas, catch exceptions on writes, and replay to the writer), but it's simpler and marginally faster to simply distinguish based on the verb.
Re:Request bodies in GET requests by abhishekjha on Monday January 31, 2022 @05:08PM (#30155293)
> route everything to replicas, catch exceptions on writes, and replay to the writer),

I am curious about the specifics here. Do you do it at the application level or proxy level?

Does doing it at the app level require that all the requests can be routed to any DB instance regardless of whether they are master or slave. A write to a mster is passed through. A read to a master is routed to slaves LB. A read on slave is passed through. A write on replica is routed to the master.

Does this look like a sound design?

Re:Request bodies in GET requests by tptacek on Monday January 31, 2022 @06:26PM (#30156306)
There's a bunch of different ways to do this, and upthread I just gave a sketch. I can tell you what we do at Fly.io --- or rather, what we suggest our users do:

* We have an HTTP header you can set in a reply that says "replay this request elsewhere".

* We boot up clusters of Postgres servers in read-replica configurations --- a single writer, lots of readers.

* If you try to write to a read replica, you get an error from Postgres, and your framework passes that error up to you.

* We suggest our users catch the exception and set the "replay elsewhere" header to redirect the request to the write master.

And that's pretty much it. Most apps are read-heavy. Reads get serviced from replicas (and, usually, close to their users --- that's the point of the service we built) and writes go to the single write master. You don't write any serious code to make that work.

But if apps could reliably say "a POST isn't just a complicated GET, but is almost certainly changing mutable serverside state", this would be an even easier problem; you'd just have the CDN route POSTs to the write master region, and GETs to the nearest region, and you'd be done.

You can architect your apps like this today, I guess, using QUERY or abusing PUT or something. My point is just that there's significant value in being able to shift all the read-only operations out of POST.

Re:Request bodies in GET requests by nine_k on Monday January 31, 2022 @06:28PM (#30156328)
GETs are idempotent and pure, at least in theory. Any replica can serve them, give an identical result, and change no data.

POST, on the other hand, is expected to mutate data. It needs to go to the master node, unless you have bidirectional replication, which is way more complex.

This is why a load balancer / proxy can spread GET requests and cache their results, but can't do so with POSTs.

QUERY is like POST in that it has a body, but is like GET in that it's idempotent, and should return the same result given the same URL and body. Load-balancing and caching work again.

Re:Request bodies in GET requests by dragonwriter on Monday January 31, 2022 @06:52PM (#30156601)
> GETs are idempotent and pure, at least in theory.

No, gets are safe (do not induce any client-responsibility state changes) and idempotent (do not induce any additional client-responsibility change of state for a second identical request with no intervening action after the first), not pure (do not depend on any state outside of the request).

Re:Request bodies in GET requests by pvg on Monday January 31, 2022 @06:43PM (#30156499)
GETs are not pure, not even in theory. If they were, you could cache the result of any GET request forever.
Re:Request bodies in GET requests by dillondoyle on Monday January 31, 2022 @10:20PM (#30158228)
Interesting that makes sense. though definitely not an issue in anything I build too small ;0
Re:Request bodies in GET requests by nrmitchi on Monday January 31, 2022 @02:54PM (#30153322)
You often want to cache results of complex queries.

If these are POST, you find yourself trying to conditionally cache POST requests, which opens up a whole new class of caching bugs.

Re:Request bodies in GET requests by NavinF on Monday January 31, 2022 @03:05PM (#30153506)
If the queries are that long (over 2k-ish bytes), wouldn’t you wanna write a query file with POST and then execute it by name with a GET?
Re:Request bodies in GET requests by wtetzner on Monday January 31, 2022 @03:23PM (#30153731)
Then you need to build infrastructure for storing queries. Depending in the specifics of the project, that may or may not be OK.
Re:Request bodies in GET requests by cryptonector on Monday January 31, 2022 @03:50PM (#30154136)
That takes two steps, needs authorization, and needs queries created that way to be stable so that when you execute them with GET you know what you're executing.

This is a lot of application logic to add just to avoid adding a QUERY method. It's just too much.

Re:Request bodies in GET requests by dastbe on Monday January 31, 2022 @03:26PM (#30153788)
while that could be preferred, here's some reasons why it may not be

1. pre-existing behavior. maybe queries have only started getting big enough to where this mattered, but all of our existing clients communicate the original way and won't migrate

2. more complex behavior on clients and services as you've now introduced a new stateful resource between client and service. should clients store query ids, or does the service handle idempotency? what db does the service use to store queries? how do we limit stored queries? do clients have to manage number of queries stored? does the service?

Re:Request bodies in GET requests by fooey on Monday January 31, 2022 @09:22PM (#30157832)
and you just re-invented stored procedures and/or RPC

pretty much the same pro's and con's too

safer, more controlled, better optimized but it's more limiting, another dev dependency and a responsibility bottleneck

Re:Request bodies in GET requests by cryptonector on Monday January 31, 2022 @03:47PM (#30154084)
If you can only use POST, then the query is by definition not safe in the HTTP sense even if it would be with a QUERY method: POST is defined to be not-safe.

So an HTTP framework would not retry, moving retry logic into the application.

If you can only use POST, then you also can't cache the result because POST is not safe: you've no idea if the same POST is intended to produce the same response.

Re:Request bodies in GET requests by jayd16 on Monday January 31, 2022 @06:31PM (#30156374)
POSTs are cacheable with a cache response header. POST MAY NOT be idempotent. That doesn't mean they MUST NOT be idempotent. If you have the cache header, you do know what the intention is.
Re:Request bodies in GET requests by dillondoyle on Monday January 31, 2022 @10:28PM (#30158284)
Makes sense on the browser retry.

Can cache in your JS code. But for browsers:

Do browsers respect cache headers for GET requests to say an API endpoint? maybe with an etag?

Re:Request bodies in GET requests by kuhzaam on Monday January 31, 2022 @02:57PM (#30153360)
Some popular web frameworks limit the size of the query string
Re:Request bodies in GET requests by cj on Monday January 31, 2022 @03:05PM (#30153504)
Popular browsers limit the size of the URL (not specifically the query string, the whole URL). If frameworks limit qs size, it’s most likely due to upstream browser limitations.
Re:Request bodies in GET requests by matsemann on Monday January 31, 2022 @03:33PM (#30153882)
CloudFront does as well. Bit us when Adyen didn't support a POST-workflow for our case, and at the time sent a GET request a thousand kilometers long instead.
Re:Request bodies in GET requests by dillondoyle on Monday January 31, 2022 @10:22PM (#30158243)
AFAIK Chrome et al do too. at a couple thousand of characters last I searched for an answer.

I did write some tracking code that ended up having really long strings and a ton of parameters and wrote it to break into multiple requests at like 1800.

Re:Request bodies in GET requests by patrickthebold on Monday January 31, 2022 @10:26PM (#30158274)
also things like proxies/load balancers. I remember being happy that I figured out how to configure my framework to allow a long url, but then sad that something in between wasn't allowing it.
Re:Request bodies in GET requests by isbvhodnvemrwvn on Monday January 31, 2022 @02:49PM (#30153262)
Caching gets rather tricky.
Re:Request bodies in GET requests by dylan604 on Monday January 31, 2022 @02:53PM (#30153309)
Maybe because caching POST data is just an odd way of doing things?