6 ms·
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 i
by 100ms 3mo 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
- davidkwast 3mo agoI would use a hash of the body content (the query) as a URL parameter /?hash=123456789
- Joker_vD 3mo agoWhy? That's pushing more work to do both on yourself and the cache.
- WorldMaker 3mo agoActually this is a use-case supported by this RFC [1]. You accept an arbitrary QUERY /search/ and you cache it on your side (or in a middle box somewhere such as a CDN edge) you can return in your response: Location: /search/?queryHash=SOMECDNHASH The browser can then cache that Location and the next time convert that same QUERY /search/ into GET /search/?queryHash=SOMECDNHASH. Sure, it is more work for your webserver to compute that and potentially the browser to cache it's knowledge of that QUERY, but it potentially gives you an advantage in keeping things like CDN edge caches generally aware of client/browser caches in a way that can be performance optimized. [1] https://www.rfc-editor.org/info/rfc10008/#section-2.4 https://www.rfc-editor.org/info/rfc10008/#section-2.4
- epolanski 3mo 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.
- Joker_vD 3mo 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 3mo 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 3mo agoWell, 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
- afavour 3mo agoIs caching not the primary reason to use this over POST? You should never want to cache POST requests.
- drdexebtjl 3mo agoNo. Being idempotent, it also lets the browser/client/reverse proxy retry it if it fails.
- nfw2 3mo agoTechnically a put or a patch is also idempotent. The benefits are idempotent and safe (and semantically appropriate). Post (generally) communicates something is changing whereas a query doesn't
- 3mo ago
- cryptonym 3mo agoSure 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 3mo agoQuery parameters are length-limited, because HTTP URIs are: https://www.rfc-editor.org/info/rfc9110/#section-4.1-5 https://www.rfc-editor.org/info/rfc9110/#section-4.1-5. There is no expectation for arbitrarily long HTTP URLs to be functioning.
- cryptonym 3mo agoYour link doesn't say URIs are length-limited
- Draiken 3mo agoI'm guessing you never hit this issue then, but it's a real issue. Whether or not it's in the RFC as a hard limit it doesn't matter, no HTTP server will allow unlimited sized URIs. You simply can't base64 large payloads and you're stuck with workarounds.
- cryptonym 3mo agoYou are guessing wrong. Thanks, I know specific implementation will come with their limits. This will equally apply to QUERY body size and caching strategy. Are we seriously ok with linking the RFC as source while providing a statement that doesn't match? RFC does matter.
- ralferoo 3mo agoThe RFC does say "It is RECOMMENDED that all senders and recipients support, at a minimum, URIs with lengths of 8000 octets in protocol elements." One can infer from the RFC that you can reasonably expect many implementations to fail beyond 8000 characters, and that there are no guarantees up to that either. True, the RFC doesn't specify a limit, but it does clearly indicate that it's not unbounded, nor should you expect it to be.
- friendzis 3mo 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".
- CodesInChaos 3mo agoThe 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 3mo agoNot 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.
- dagss 3mo agoDo you have to? Is it common to treat ?a=1&b=2 the same as ?b=2&a=1 in browser/CDNs/etc? Seems the spec puts this as a MAY. I think I doubt it will be implemented in generic ways, except perhaps for urlencoded payloads. After all you cannot normalize in general without knowing the query language. At the backend it does not matter, may as well cache one level deeper based on the parsed input irrespective of QUERY or not.
- ralferoo 3mo agoNo, that was my point. In a GET request, a caching proxy cannot assume the URL is URL encoded parameters, because the URL can contain data encoded in any form. So, you could only cache a GET on an exact URL. But for a QUERY that explicitly marked the data as multipart or url-encoded, then semantically the order of parameters no longer matters. That said, it's hypothetical because the only thing that uses those at the moment is POST and that explicitly should never be cached. But there's another reply above to my comment that points out that a caching implementation is free to do what it likes, and if it fails to cache when parameters are in a different order, then it would still be correct, which is a fair point. That comment was https://news.ycombinator.com/item?id=48578024 https://news.ycombinator.com/item?id=48578024
- wang_li 3mo agoIf 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.
- inigyou 3mo agoNot 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 3mo agoExcept 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 3mo agoPOST/QUERY data can be in any format. Who are you to say order doesn't matter? Are you sure you can even parse it? Mine is in DES-encrypted (with key "password") base85 DER, you really gonna implement that in your proxy?
- ralferoo 3mo agoMaybe my knowledge is out of date in terms of how people generally use POST nowadays, but AFAIK multipart/form-data is still the most common encoding for data and occasionally application/x-www-form-urlencoded. Both of these, the key values can be in any order with the same interpretation. That's kind of a moot point for POST method, because they should never be cached anyway, but for the new QUERY method it'd be reasonable to expect a cache hit whenever the parameters are the same regardless of order. My point is that for a GET, you can't assume that the order isn't important, because the URL is an opaque string by the time it hits the cache. However, POST (and now QUERY) explicitly says what the coding is, so for instance with application/x-www-form-urlencoded we can be sure that the parameters can be in any order without changing the meaning. You cannot infer that from a URL itself. As to your point, yes you can use any other encoding you like to. But most systems don't do that, they use multipart/form-data.
- tanepiper 3mo agoOne 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.
- ygouzerh 3mo agoRegarding the body used as a key for the caching: in the RFC, from my understanding, it's indicated that we can use Location as well: 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
- speleding 3mo agoI 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.
- sablekit 3mo ago[flagged]
- lightningspirit 3mo agoThis 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.