New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Request with GET/HEAD method cannot have body. #551
Comments
HTTP allows a request body on GETs syntactically so that message parsing is generic; it doesn't say that a body has any meaning on a GET. So, anyone using a body on a GET is effectively "off the reservation"; they're not longer using HTTP, but defining their own private protocol. Since Fetch is an API for HTTP, it's entirely reasonable for it not to allow this. More practically, using bodies on GETs tends to trigger interop problems with proxies, CDNs, servers, etc. While it might work in the lab or even on the Internet under controlled conditions, using it at scale is very likely to bump into this. For example, users who have virus scanning proxies are likely to have problems, since they tend to have very conservative implementations. |
Mark, thanks for your response. This isn't about me or any individual wanting to use a body on a GET. It's about the fact that it is used in industry which you can see in the ElasticSearch documentation which I linked in my first post. ElasticSearch is used at scale in industry. Don't try to convince me not to use it. Convince people like Elastic company not to use it. My point is, I don't think additional rules should be added to a spec even in parts where the spec isn't explicitly clear, especially when it can be shown that it limits certain industry applications. |
If we changed how we use HTTP (or TCP, or any other protocol) to accommodate every abuse in "industry" like this, we'd quickly lose all of the value of having a shared protocol. Get them to fix their software, don't try to convince everyone else to accommodate their non-standard use. |
Duplicate of #83. As far as I know nothing changed since then. |
Doing something that is allowed within the HTTP spec is hardly abuse. It seems odd that the creators of this get to dictate how APIs should and should not work...
Well, you should take your own words to heart because what people are trying to accomplish is definitely according to standard... |
So far I could reference the following arguments against the addition (in fact it is a suppression) of this:
Please consider that all people that wrote messages about this concern aren't trolling or trying to enforce a point of view. Sending a GET Request with a body is used widely in the industry and is not explicitly forbidden by the RFC. Refusing to allow it for the reasons that I listed is just being conservative and reactionary. It does not promote progress in the slightest. |
Elasticsearch rest api requires sending a body with a GET. Please at least provide an option for disabling this. Sending a body with GET is part of the standard. |
If some specific platforms/frameworks reject handling GET/HEAD requests with a body, those who use them will work around by making bodyless GET/HEAD requests or switching to standard compliant platforms/frameworks. There are already platforms/frameworks handling GET/HEAD requests with a body, some of them also handle security and caching. It isn't right to enforce non-standard behavior on the fetch API. |
I recommend reading #83 for some background as to why this is not that simple. But really, if you can convince browsers to add this and overcome the hurdles discussed there, it'd happen. Advocacy here is unlikely to help with that though. |
(Also, |
@annevk Using a non-standard HTTP method is not an acceptable solution to a non-standard HTTP behavior. Browsers follows the Fetch API standard, and suggesting otherwise is a bad call. There is a HTTP standard. There is Fetch API standard. Fetch API works using HTTP, so it should be compliant with HTTP standard unless it cause a security breach. |
Can you be more specific about this? Which unique considerations are there for the browser application that makes it so difficult to allow this in the Fetch standard? I mean, keep in mind that if somebody really wants to send a GET with a body, they can do it with any other application. The issue with that is many developers want to implement internal tools as browser apps because it is convenient and safe. |
It's as simple as allowing new things to be send to unsuspecting servers. Non-browser applications might not necessarily have the same state or run on the user's computer and therefore have access to the user's private network. The bigger problem is lack of implementer interest though, as noted above. |
I agreed with the fact that it is not really a standard way and import https from 'https';
import http from 'http';
const requestWithBody = (body, options = {}) => {
return new Promise((resolve, reject) => {
const callback = function (response) {
let str = '';
response.on('data', function (chunk) {
str += chunk;
});
response.on('end', function () {
resolve(JSON.parse(str));
});
};
const req = (options.protocol === 'https:' ? https : http).request(options, callback);
req.on('error', (e) => {
reject(e);
});
req.write(body);
req.end();
});
};
// API call in async function
const body = JSON.stringify({ a: 1});
const result = await requestWithBody(body, options = {
host: 'localhost',
port: '3000',
protocol: 'http:', // or 'https:'
path: '/path',
method: 'GET',
headers: {
'content-type': 'application/json',
'Content-Length': body.length
}
};
) |
This might bring some clarity. Not that favors one side or the other but at least brings context to the conversation. |
From what I read in this issue and the associated comments, I see that the refusal is based on a theoretical vulnerability. I have put a great deal of thought about this but I fail to see how sending a body with a I also read the RFC again - and the comments on the Elasticsearch issue are pretty clear about that as well - I still fail to see where the RFC forbids to have a body using a |
httpwg/http-core#202 is something of a focal point for this conversation, and was resolved by updating the latest HTTP spec draft in httpwg/http-core@f34f677 to include the explanation you're asking for:
It's not so much that HTTP clients are strictly forbidden from including content in a GET request, it's that HTTP servers may not use such content. |
So basically they're asking for people to bypass the standard completely and only use POST for everything just so they could use clean payloads without obstacles. |
Just a question here, not advocating for any side in the debate :) I'm a bit confused if this is a restriction in the Fetch specification or in Fetch implementations. If it's a spec thing, could someone point me to the relevant lines in https://fetch.spec.whatwg.org/? Tried to find what methods should support bodies but was unable to. |
Rather than fix the implementation, they opted to subset the HTTP specification to fit the implementation of fetch(). Rule 33 of "The new Request(...) constructor steps are:" https://fetch.spec.whatwg.org/#dom-request
Which prevents doing clean call with complex nested structures like the fake code below.
If you wanted to make a proper API to handle front & back interactions, you can't. |
This is not true, it's the other way around. |
Exact ! What we can be certain of is that browsers, OS, proxies, ... will never bother implementing something that is explicitly forbidden by the standard. The way it works is :
Being allowed by the standard is the first step. The only reverse situation is when you have a step 0) But it will never happen if that feature is forbidden by the standard. |
Also, the Fetch API (and thus the DOM API overall) is establishing the standard for browsers. It's not up to browsers to determine if they feel like implementing it or not. If they don't, then they will fall behind technologically speaking and will end up like Internet Explorer. |
I tried using
Workaround for Nodejs runtimes (not in browser ... JS on the server)Unfortunately the API I'm working with I cannot change at this time so I needed a work around. // only works in node / server -- i have not tried in the browser
const res = await axios.get("/api/devices", {
data: { deviceName: 'name' }
}) |
It will not work in browser because the available APIs don't allow it. Also note that on some operating systems it won't work because the underlying HTTP implementation does not allow it. IIRC that includes iOS and Windows. In theory you could implement an HTTP client from scratch using lower level network APIs and guarantee the ability to have a body in GET requests... But still can't do this in browser because such low level APIs are not available. |
I ran into this restriction while building HTTP functions for a library. I think this should be reconsidered because sometimes people actually use the body in a GET request. Notably, ElasticSearch can use it for queries. It can use the querystring instead, but that can be pretty cumbersome which is why it also accepts a body for GET queries.
https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-body.html
Since I'm making a library I want to allow everything within the specification of HTTP but apparently fetch has its own rules, and as you can see it's possible for that to interfere with using an API._
You'd think this is an edge case, but if it interferes with something like ElasticSearch maybe it's not an edge case._
The text was updated successfully, but these errors were encountered: