FYI: QUERY is for GET requests where the query string make the URL too long. It does this by sending a body like POST.
In the past, POST meant you were sending a body, and GET meant you received a body. And the people got religious about a pseudoacronym called REST.
With HTTPS used almost everywhere, using this QUERY method (when standardized) could prevent bookmarking specific “GET” URLs if the developers thoughtlessly replace GET everywhere with QUERY.
One of the advantages of GET is the direct visibility, which makes modifications simple and easy for almost anyone (end users, testers, etc.).
The larger question I have is who will choose to adopt it sooner, with web servers, web application frameworks and web browsers in the mix.
If today you're doing some JS-fu to make an ajax GET request then you already need to do something to have permalinks (if desired).
Completely worth bringing up and thinking about, but unless I'm missing something I don't think a QUERY verb will change all that much here?
The semantics are important. GET APIs are expected to be safe, idempotent, and cache-friendly. When you are unable to use GET for technical reasons and move to POST, suddenly none of the infrastructure (like routers, gateways, or generic http libs) can make these assumptions about your API. For example, many tools will not attempt to put retry logic around POST calls, because they cannot be sure that retrying is safe.
Having the QUERY verb allows us to overcome the technical limitations of GET without having to drop the safety expectations.
> 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 (Section 11.2 of [HTTP/1.1]). 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.
QUERY is a new option to help avoid some of those downsides.
You're bothering about non-issues. Bookmarks support GET requests, not any other verb. Like it has always been, if you need to support bookmarks then you implement bookmarkeable URLs to be used with GET requests.
Also, your far-fetched example failed to account for the fact that nowadays POST requests are used to query.
Obviously query parameters are not going anywhere, but if this achieves enough adoption there is a future down the road where we can stop using POST for any query that wants a payload, without needing to change every single HTTP client in the world. (Many of them can already understand custom methods and treat them basically like posts.)
PathInfo is a thing you can absolutely use.
Presumably, because of that, many pages will continue to use query parameters for the foreseeable future. I think that's fine, but at least for APIs, the QUERY method could eventually be a very nice thing to have.
It's felt quite awkward to tiptoe around the existing spec when building features that retrieve data; we've had to either use POST to keep sensitive filter criteria out of http logs or just create a usually massive URL-encoded query string.
This allows the GET to bypass the 4k URL limit.
It's not a common pattern, and QUERY is a nice way to differentiate it (and, I suspect will be more compatible with Middleware).
I have a suspicion that quite a few servers support this pattern (as does my own) but not many programmers are aware of it, so it's very infrequently used.
If you’re sending over TLS (and there’s little reason why you shouldn’t these day) then you can limit these caching issues to the user agent and infra you host.
Caching is also generally managed via HTTP headers, and you also have control over them.
Processing might be a bigger issue, but again, it’s just any hosting infrastructure you need to be concerned about and you have ownership over those.
I’d imagine using this hack would make debugging harder. Likewise for using any off-the-shelf frameworks that expect things to confirm to a Swagger/OpenAPI definition.
Supplementing query strings with HTTP headers might be a more reliable interim hack. But there’s definitely not a perfect solution here.
And as much as it may disregard the RFC, that's not a convincing argument for the customer who is looking to interact with a specific server that requires it.
I don’t think it’s unreasonable to expect your sysadmins, devops, platform engineers, or whatever title you choose to give them, to set up these services correctly, given it’s their job to do so and there’s a plethora of security risks involved.
If you can’t trust them to do that little, then you’re fuck regardless of whether you decide to send payloads as GET bodies.
And there isn’t any good reason not to contract pen testers to check over everything afterwards.
Exactly, and the correct way to setup GET requests is to ignore their bodies for caching purposes because they aren't expected to exist: "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" (RFC 9110)
> And there isn’t any good reason not to contract pen testers to check over everything afterwards.
I am pretty sure our SecOps and Infra Ops and code standards committee will check it and declare that GET bodies is a hard no.
No. The correct way to set up this infra is the way that works for a particular problem while still being secure.
If you’re so inflexible as an engineer that you cannot set up caching correctly for a specific edge case because it breaks you’re preferred assumptions, then you’re not a very good engineer.
> and might lead some implementations to reject the request and close the connection because of its potential as a request smuggling attack"
Once again, you have control over the implementations you use in your infra.
Also It’s not a RSA if the request is supposed to contain a payload in the body.
> I am pretty sure our SecOps and Infra Ops and code standards committee will check it and declare that GET bodies is a hard no.
I wouldn’t be so sure. I’ve worked with a plethora of different infosec folk from those who will mandate that PostgreSQL needs to use non-standard ports because of mandating strict compliance with NIST, even for low risk reports. To others that have been fine with some pretty massive deviations from traditionally recommended best practices.
The good infosec guys, and good platform engineers too, don’t look at things in black and white like you are. They build up a risk assessment and judge each deviation on its own merit. Thus GET body payloads might make sense in some specific scenarios.
This doesn’t mean that everyone should do it nor that it’s a good idea outside of those niche circumstances. But it does mean that you shouldn’t hold on to these rigid rules like gospel truths. Sometimes the most pragmatic solution is the unconditional one.
That all said, I can’t think of any specific circumstance where you’d want to do this kind of hack. But that doesn’t mean that reasonable circumstances would never exist.
Running PostgreSQL on any non-privileged port is a feature, not a deviation from a standard. If you want to run PostgreSQL on a port under 1024 now that would be security vulnerability as it requires root access.
There is no reason to "build up a risk assessment and judge each deviation on its own merit" unless it is an unavoidable technical limitation. Just don't make your life harder for no reason.
That's clearly not true. You're now just exaggerating to make a point.
> I am struggling to even imagine how one could make an L7 balancer that should take into account possibilities that someone would go against HTTP spec and still get their request served securely and timely
You don't need application-layer support to load balance HTTP traffic securely and timely.
> Running PostgreSQL on any non-privileged port is a feature, not a deviation from a standard. If you want to run PostgreSQL on a port under 1024 now that would be security vulnerability as it requires root access.
I didn't say PostgreSQL listening port was a standard. I was using that as an example to show the range of different risk appetites I've worked to.
Though I would argue that PostgreSQL has a de facto standard port number. And thus by your own reasoning, running that on a different port would be "insecure" - which clearly is BS (as in this rebuttal). Hence why I called your "de facto" comment an exaggeration.
> There is no reason to "build up a risk assessment and judge each deviation on its own merit" unless it is an unavoidable technical limitation.
...but we are talking about this as a theoretical, unavoidable technical limitation. At no point was anyone suggesting this should be the normal way to send GET requests.
Hence why i said you're looking at this far too black and white.
My point was just that it is technically possible when you said it wasn't. But "technically possible" != "sensible idea under normal conditions"
For one, you’re wrong about TLS meaning only your infra and the client matter. Some big corps install a root CA on everyone’s laptop and MITM all HTTP/S traffic. The one I saw was Bluecoat, no idea if it follows your expected out-of-spec behavior or not.
For two, this is likely to become incredibly limiting at some point and require a bunch of work to re-validate or re-implement. If you move to AWS, do ELBs support this? If security wants you to use Envoy for a service mesh, is it going to support this? I don’t pick all the tools we use, so there’s a good chance corporate mandates something incompatible with this.
You would need very good answers to why this is the only solution and is a mandatory feature. Why can’t we cache server side, or implement our own caching in the front end for POST requests? I can’t think of any situations where I would rather maintain what is practically a very similar fork of HTTP than implement my own caching.
To be clear, I'm not advocating it as a solution either. I'm just saying all the arguments being made for why this wouldn't work are solvable. Just like you've said there that it's doable.
> Some big corps install a root CA on everyone’s laptop and MITM all HTTP/S traffic.
I did actually consider this problem too but I've not seen this practice in a number of years now. Though that might be more luck on my part than a change in industry trends.
> this is likely to become incredibly limiting at some point and require a bunch of work to re-validate or re-implement.
I would imagine if you were forced into a position where you'd need to do this, you'd be able to address those underlying limitations when you come to the stage that you're re-implementing parts of the wider application.
> If you move to AWS, do ELBs support this?
Yes they do. I've actually had to solve similar problems quite a few times in AWS over the years when working on broadcast systems, and later, medical systems: UDP protocols, non-standard HTTP traffic, client certificates, etc. Usually, the answer is an NLB rather than ALB.
> You would need very good answers to why this is the only solution and is a mandatory feature.
Indeed
I think that violates the HTTP spec. RFC 9110 is very clear that content sent in a GET request cannot be used.
Even if both clients and servers are somehow implemented to ignore HTTP specs and still send and receive content in GET requests, the RFC specs are very clear that participants in HTTP connections, such as proxies, are not aware of this abuse and can and often do strip request bodies. These are not hypotheticals.
"Your GraphQL HTTP server must handle the HTTP POST method for query and mutation operations, and may also accept the GET method for query operations."
Supporting body in the get request was an odd requirement for something I had to code up with another engineer.
The docs state that is query is in the URL parameters, that will be used.I remember that a few years back it wasn't as easy - you HAD to send the query in the GET requests body. (Or it could have been that I had a monster queries that didn't fit through the URL character limits.)
0: https://www.elastic.co/docs/api/doc/elasticsearch/operation/...
I remember this pain, circa 2021 perhaps?
I think this comment is terribly naive. Technically you can write your own service to support verbs like LOL or FUBAR, but in practice your service is not only expected to be broken when passing requests through other participants you do not control but also it requires far more development work to integrate with existing standards. Take for example CORS. If a HTTP method is not deemed safe then client requests need to go through the unsafe flow with preflight requests and the like. Forget support for caching too, and good luck having your requests pass through proxies.
So what exactly did you achieved by using non-standard verbs?
If you chose to go the ignorant backwards incompatible way, you are better off not using HTTP at all and just go with some random messaging/RPC protocol.
The cases tend to look like this: - An endpoint was implemented as a GET endpoint, since it’s for getting data, with the search terms in the query parameters. The search term got too long, breaking a critical behavior in production environments. - An endpoint was implemented as a POST endpoint, despite it being an idempotent query for data, since the request body is too large to fit in query parameters. New employees repeatedly come in and are confused why it’s not a GET endpoint, or why it doesn’t modify anything.
I know this densest really work with ad-hock and cheap queries but it does for more expensive / report style ones.
https://lists.w3.org/Archives/Public/ietf-http-wg/
There's also some tracking on GitHub.
https://github.com/httpwg/http-extensions/issues?q=label%3Aq...
I encountered a codebase with only POST for all operations, given my lack of knowledge in this area, I am not sure why one would choose POST only over the standard set of GET, PUT, POST, DELETE, etc.
... and they don't use GET everywhere because one time Google scraped that endpoint and dropped the production database.
POST: I want to change stuff.
I don't know how this style cannot match cleanly any architecture.
It's not supposed to be a map to CRUD, it's a bunch of building blocks for manipulating state over a network.
Most likely, you would benefit from making a cirurgical mini-resource on the server.
Introduce `/report/{id}`, and make it into a POST.
The user POSTs to `/report`, and the answer is 201 (Created) or 202 (Accepted), with a `Location: /report/123` (generated short id). The thing you changed on the server, is that now that long list have a short id. Just that.
Then, the user `GET /report/123` (auto redirect). It all happens within the same socket (keep-alive) and it has almost zero overhead (one refresh without this probably has thousands of times more overhead than the redirect).
By doing that, it seems that you are wasting stuff, but you're not.
Now the user doesn't have to transfer huge amounts of query data when GETing the results again, cache layers will have an easier time, and you can even use that mini-resource as a shortcut to solve things like racing conditions (two users doing the same humongous query at the same time).
Realistically, unless you're some query-by-image type of thing (trying to search images that match an existing one), you'll never actually have to face URL limits. If you are one of those cases, then you probably already have other architectural constraints that would justify introducing the extra intermediate resource.
That would explain a some of the design decisions. I had to do work on a old codebase and am studying it.
Thank you and the others too for the input.
--
PUT: I want to replace stuff.
DELETE: I don't want anyone to GET that stuff anymore.
HEAD: I want to peak at how stuff is shown.
OPTIONS: I want to know what I can do with stuff.
--
COPY: I want to copy stuff (WebDav)
MOVE: I want to move stuff (WebDav)
MKCOL: I want a new sublevel of stuff (WebDav)
PROPFIND: I want to list stuff (WebDav)
PROPPATCH: I want to mass change stuff (WebDav)
LOCK: I want to control who METHODs stuff.
UNLOCK: I want to remove control over who METHODs stuff.
--
All of those are actually optional. It is okay to use POST[0]. GET and POST with proper hypermedia (media types and links) is all 99% of apps need.
[0]: https://roy.gbiv.com/untangled/2009/it-is-okay-to-use-post
That's also why I only use a couple of status codes: Ok, Created, NoContent, BadRequest, Forbidden, Unauthorized an InternalServerError (the latter two generated automatically by the framework).
GET, PUT, DELTE, etc. seem to be tailored towards entities, but as soon as the endpoint is not an "entity", the semantics get vague and break down.
Looking at the logs I see that most of the long URI traffic is due to UTM and other tracking related codes, which are mainly a way to work around 3rd party cookie blocks.
I must be missing something, because it sounds like to goal is to have longer URI without the need for encoding URL parameters, but without using POST.
Suppose you have one filter but it has a few hundred twenty-character values.
Also another case is as a dev you are dealing with guids all day and it can be fast to swap guids around in the browser bar vs. ui steps.
That is perfectly fine. Sites that support path- and query-based filters are already designed specifically to have filters embedded in links, which are GET requests. The QUERY method is something more in line of a GraphQL style of query that isn't held back by the semantics of a POST request. GraphQL didn't invented this API style. If GraphQL-style APIs didn't affected how WebApps implemented links, QUERY methods won't.
I love the idea of a separate verb. It always felt like get is just not quite enough.
WHERE id IN (id1, id2, id3, ...);For example, this one is: https://datatracker.ietf.org/doc/draft-ietf-httpbis-safe-met...
The best way to view an RFC, IMHO, is to use the "htmlized" format: you can view and compare different versions, view errata for a formal RFC, and go back to Datatracker at any time.
Also, the Datatracker URL is version-insensitive, so unlike the pure HTML format, it will not be stuck on draft-14 forever.
Also, the previous SEARCH method was proposed in Apr 2015 (!!), but nobody took it seriously, and it never gained traction back then. A lot of software was developed/updated during the last decade, and a lot of opportunities were missed. Even if the QUERY method is turned into a formal RFC right now, expect 10+ years for everyone to adopt it, without running into HTTP-405 or 501's.
See the history of the PATCH method, and of the whole WebDAV thing.
On my phone, your Datatracker link results in an unreadable mess of a page due to the hard-coded line breaks in the plaintext rendition of the RFC text (making it unreadable in portrait mode) and the huge sticky page nav (causing the content viewport to shrink vertically to almost zero in landscape mode). The HTML page behind OP's link reads just fine.
> The best way to view an RFC, IMHO, is to use the "htmlized" format
I don't see any choices of format such as HTML behind your link. There's a sticky nav, then a couple of pages of metadata, followed by a plaintext rendering of the RFC. What am I missing?
echo https://www.ietf.org/rfc/rfc$1.txt|yy025|nc -vv 6f6b 80|yy045|less
yy025 makes custom HTTP, more flexible than curl6f6b is TLS forward proxy
yy045 removes chunked encoding
less is more(1)
For drafts I use a metasearch script
+1 for non-paginated results
;;64) #``````````` datatracker
shift
x=$(echo "$x"|sed 's/ /+/g;s/++/+/g')
echo "https://datatracker.ietf.org/doc/search?name=$x&activedrafts=on&olddrafts=on"|yy025|(yy084 64 "$x";nc -vv 6f6b 80)
exit
yy084 makes SQL from SERPWaste of time.
POST to /reports with the query parameters in the body. Respond with bookmarkable, cacheable /reports/id and GET /reports/id
And that’s only necessary for huge, complex queries. If filtering some resources doesn’t fit into the URL you might want to rethink what you’re doing.
Not as good as a standardized idempotent Method, but good enough for the time being till they finally approve this as RFC
Obviously doesn’t work with all systems, but QUERY works with even fewer.
chronicler•2mo ago
platzhirsch•2mo ago
Veserv•2mo ago
What you are actually doing when making a specific kind of request is assuming the actual properties match the documented properties and acting accordingly.
A QUERY seems to be no more than a POST that documents it is idempotent. Furthermore, you should only QUERY a resource that has advertised it is idempotent via the “Accept-Query” header. You might as well name that the “Idempotent-Post” header and then you just issue a POST; exactly the same information and properties were expressed and you do not need a new request type to support it.
happytoexplain•2mo ago
Veserv•2mo ago
This is literally expressed in the document in section 1: Introduction. They just want to take that POST request and replace the word POST with QUERY which also means the server is intended to assure the request is idempotent instead of needing that documented out-of-band.
johncolanduoni•2mo ago
dragonwriter•2mo ago
It focuses on a bit more on safety, which is why every mention of it the proposed method having the "idempotent" property is immediately preceded (in most cases in the same sentence) by description of it having the "safe" property.
pcthrowaway•2mo ago
It's clear what POST returns, so... perhaps QUERY is more similar to it in that sense?
johncolanduoni•2mo ago
LoganDark•2mo ago
Veserv•2mo ago
When considered abstractly, POST is just a request body and a response body. This is obviously powerful enough to define any behavior you want; it is just a channel flowing a nearly arbitrary amount of opaque data between the client and server.
However, this kind of sucks because it does not define or constrain the behavior of the client or the server. QUERY says that the server is intended to interpret the request body as fetch parameters and return a response body as the fetched data, and further guarantee that the fetch is safe/idempotent. This is very useful.
My disagreement is that there is no good reason for the client request format to care. You should “POST” to a “QUERY” endpoint. The fact that this endpoint guarantees QUERY behavior is just part of the documented server interface in the same way that certain endpoints may not support PUT. This is a server constraint, not a client constraint so should not change the client transport format.
Requiring a new Client request type to agree with a new Server endpoint type is just unnecessary and mixes up server versus client responsibility and interface design.
happytoexplain•2mo ago
Veserv•2mo ago
A client can blindly PUT a endpoint that does not support PUT, only GET. In the cold connection case where does this fail? The client succeeds at serializing the message, the client succeeds at sending it, the message gets successfully received, and only upon examining the message itself does the server know it should not follow the client intent. This is the same behavior as if the client sent garbled nonsense.
The key here is that it is the server demanding certain message structures. The client is free to send whatever, it just only succeeds if it sends something the server will accept. The server distinguishes, but to the client it is no different from sending any other opaque blob of data. This is thus just a server-constraint, the endpoint is GET-only. To use this website/HTTP interface, the client needs to know that.
It will need to know to format the message correctly, but that derives from knowledge of the documented server interface. If you had just a direct connection with no intermediary participants, then you could trivially swap out HTTP for any other transport protocol without a loss of functionality or behavior. That points to there being no reason to syntactically distinguish on the client to server leg of the transport protocol. However, you still have GET endpoint behavior since that is actually preserved across transport changes, so that is the important class of behavior to define.
The opposing point here is that if you do have intermediarys then they may care about the message format and you may need to syntactically distinguish them. I suspect this is less beneficial than a simpler and more flexible, yet precise transport format.
Basically, we should prefer simple, flexible transport formats and push interpretation (and thus behavior) out to the endpoints which actually have enough context to know the true properties of what they are doing.
ahtihn•2mo ago
And how do you communicate this behavior to the client (and any other infrastructure in-between) in a machine-readable way?
dragonwriter•2mo ago
simonkagedal•2mo ago
dragonwriter•2mo ago
The specific definition is in the HTTP spec, and I don't think I can describe it more concisely without losing important information necessary for really understanding it.
https://www.rfc-editor.org/rfc/rfc9110#section-9.2.1
paulddraper•2mo ago
cortesoft•2mo ago
Veserv•2mo ago
The interpretation of a request is up to the server. There is no reason for the client to syntactically distinguish that the request body is for a POST vs QUERY; the request parameters and response have the same shape with the same serialization format.
However, on the other side, a server does control interpretation, so it is responsible for documenting and enforcing how it will interpret. QUERY semantics vs generic POST semantics is a receive/server-side decision and thus should not be a syntactic element of client requests, merely a server description of endpoint semantics (“QUERY endpoint” meaning shorthand for POST endpoint with query semantics).
edit: Thinking about it some more, there is one possible semantic difference which is that a transparent caching layer could use a syntactically different POST (i.e. QUERY) to know it should be allowed to cache the request-response. I do not know enough about caching layers to know how exactly they make fill/eviction choices to know if that is important.
cortesoft•2mo ago
The point is to have a standard, so you can more easily learn what an API is doing instead of having to start from scratch every time.
notatoad•2mo ago
Your GET request can modify state. But if your request exceeds a browser’s timeout threshold, the browser will retry it. And then you get to spend a few days debugging why a certain notification is always getting sent three times (ask me how I know this)
Similarly, you can put a body on your GET request in curl. But a browser can’t. And if you need to move your server behind cloudflare one day, that body is gonna get dropped.
locknitpicker•2mo ago
This is false.
By design QUERY is both safe and idempotent. In the context of HTTP, safe means "read-only", whereas idempotent means that a method does not introduce changes on the server, and thus many requests have the same effect of posting a single request.
The fact that the semantics of an operation is deemed safe has far-reaching implications in the design of any participant of a HTTP request, including firewalls, load balancers, proxies.
> You might as well name that the “Idempotent-Post” header and then you just issue a POST;
This is outright wrong, and completely ignores the semantics of a POST request. POST requests by design are neither safe not idempotent. You do not change that with random request headers.
Veserv•2mo ago
Outright wrong. You are allowed to handle POST requests in a safe and idempotent way. In fact, the existing usage of POST to query, the literal impetus for this proposal, has exactly that behavior.
What you are not allowed to do is assume that any arbitrary POST request is safe and idempotent.
Only a endpoint that is documented to support POST and that is documented to be idempotent and safe should be sent a POST with request body and expect a response body and be idempotent and safe.
In comparison, only a endpoint that is documented to support QUERY (which implicitly is documented to be idempotent and safe) should be sent a QUERY with request body and expect a response body and be idempotent and safe.
Do you not see how similar those two are?
In fact, you could trivially make every endpoint that handles QUERY just do the same thing if it gets a POST. So why should the client have to care what request type it sends? Why make a new request type?
Of course we should want to define a standardized QUERY server endpoint behavior and document whether a server endpoint has QUERY behavior on POST; that is valuable, but that should be left distinct from the client protocol and constraints.
The only benefit I can see for the client to distinguish QUERY from POST is that it allows intermediate layers to know the request is expected to be idempotent and safe on the incoming edge. The outgoing edge is not benefitted because the server can easily tag things appropriately.
I guess a cache can use that information to only begin allocating a cache entry if the client attempts a QUERY thus saving it from tentatively recording all requests on the chance that the server will say that the actual request that occurred is safe? And that is assuming that the cache does not coordinate with the server to just pre-know what endpoints are safe and idempotent. In that case all the cache would need to do is parse the location to verify if it matches a safe endpoint. So your benefit of adding a new request type is you get to “unga-bunga is QUERY” instead of doing some parsing and matching overhead.
Seems like a weak benefit relative to the benefits of a simpler and more uniform client protocol.
locknitpicker•2mo ago
You clearly have no idea about what you are discussing. The definition of HTTP verb semantics clearly defines the concept of safe and idempotent methods. You should seriously learn about the concept before commenting on discussions on semantics. If that's too much work, RFC 9110 clearly and unambiguously states that only the GET, HEAD, OPTIONS, and TRACE methods are defined to be safe. Not POST.
It's completely irrelevant if you somehow implemented a POST method that neither changes the state of the server nor returns the same response whether you invoke it once or many times. All participants in a HTTP request adhere to HTTP's semantics, and thus POST requests are treated as unsafe and non-idempotent by all participants. That affects things like caching, firewalls, even security scanners. The HTTP specs determine how all participants handle requests, not just the weekend warrior stuff someone chose to write in a weekend.
Veserv•2mo ago
The behavior and constraints of a generic interface is a lower bound on the behavior and upper bound on the assumable constraints by all direct participants when handled in general. This is POST in general. This is the weakest usage.
A specialized interface may enhance behavior or tighten constraints further. This is actually using POST to achieve some website-specific end. You can not actually use a website/reason about usage in anything other than a read-only fashion without knowing what the endpoints actually do and when to issue requests at which endpoint.
Indirect or intermediary participants should maintain behavior and constraints at the lower of the level of specialization they are aware of and the participants they are between. If you are designing a generic intermediary, then you do not have access to or knowledge about the specialized interfaces, so are less able to leverage specialized behavior or constraints. In HTTP, various headers serve the purpose of communicating various classes of common interface specializations so someone can write more powerful generic intermediarys. However, you could always write a specific intermediary or handler if you control portions of the chain, which people do all the time.
This applies across all classes of software interfaces and protocols not just websites using HTTP. But I guess HTTP is just such a special snowflake that it is beyond learning good practice from other fields.
cortesoft•2mo ago
locknitpicker•2mo ago
This is outright false. RFC9110, which clarifies semantics of things like GET requests, is clear on how GET requests should not have request bodies because it both poses security issues and breaks how the web works.
Just because your homemade HTTP API expects a GET request packs a request body, that does not mean any of the servers it hits between your client and your server will. Think about proxies, API gateways, load balancers, firewalls, etc. Some cloud providers outright strip request bodies from requests.
The internet should not break just because someone didn't bothered to learn how HTTP works. The wise course of action is to create a new method with specific semantics that are clear and actionable without breaking the world.
cortesoft•2mo ago
Obviously you can’t just start putting bodies in GET requests, because it breaks the current spec.
locknitpicker•2mo ago
This is fundamentally wrong. The semantics are not the same, regardless of whether there's even a request body or not. The semantics are completely different. One is safe and idempotent, whereas the other is neither safe nor idempotent. The presence of a body doesn't even register as a factor.
> If we are creating a new HTTP spec
Also wrong. It's all about specifying another HTTP verb. HTTP is already specified to support other verbs.
> we could give GET and QUERY be the same because they serve the same semantic purpose.
QUERY is a GET that is designed to pass query parameters in request bodies, which GET explicitly does not support. They are separate operations which just so happen to be both safe and idempotent.
badbotty•2mo ago
vlovich123•2mo ago
ashu1461•2mo ago
bhawks•2mo ago
Adding a new http method is the only way to support something like this safely. If something in between doesn't know what to do with QUERY it can just respond with a 501.
Fun fact - GET and HEAD are the only required methods one needs to implement to be an http server. It is a pretty low bar :)
chronicler•2mo ago
locknitpicker•2mo ago
The RFC is pretty clear that no participant in a HTTP request is expected to even allow a GET request through. RFC 9110 even states quite clearly that it's even a potential request smuggling attack. Some major cloud providers provide API Gateway implementations that outright strip request bodies from GET requests.
I think you are missing the whole point of proposing a new HTTP verb. Changing the semantics of a GET request is not an option because of both the security risks it presents and the fact that the infrastructure of the whole internet either is designed to reject these requests or outright breaks. See how GET requests are cached and how cache implementations don't discriminate GET requests based on it's request body.
vbezhenar•2mo ago