What kind of issue is this?
[ ] Question. This issue tracker is not the place for questions. If you want to ask how to do
something, or to understand why something isn't working the way you expect it to, use Stack
Overflow. https://stackoverflow.com/questions/tagged/okhttp
[x] Bug report. If you’ve found a bug, spend the time to write a failing test. Bugs with tests
get fixed. Here’s an example: https://gist.github.com/swankjesse/981fcae102f513eb13ed
[ ] Feature Request. Start by telling us what problem you’re trying to solve. Often a solution
already exists! Don’t send pull requests to implement new features without first getting our
support. Sometimes we leave features out on purpose to keep the project small.
I'm trying to do a get request to Elasticsearch with a query body but OkHttp doesn't allow that. The query works with curl:
curl -XGET 'localhost:9200/fncd/event/_search?scroll=1m' -d '
{
"query": {
"range" : {
"lastUpdated" : {
"gte": 1486184400000
}
}
}
}
'
OkHttp doesn’t support bodies for GET requests. For one reason, it makes caching too difficult to reason about.
Will the change in PR #3038 fix this? Is there a timeframe on when that will be released?
It’s unlikely we’ll ever support request bodies with GET.
No further action to take on this.
Is there any reason why you did not plan to support this? It will be quite useful to use it, for instance when testing elasticsearch queries like in the example of the question. (Had the same problem xD)
OkHttp is an opinionated HTTP client. By constraining what we support to what the specs allow, we’re able to keep things relatively simple and offer great features like smart caching.
Elasticsearch is wrong for exposing APIs that use GET requests with bodies. They should fix their API.
please
@swankjesse Could you please reopen this? While it was true that in the distant past the HTTP forbade the server from processing the body of GET requests, any such passages indicating this were specifically removed from RFC7230-7237 [it did always permit clients to send them!]. There is no argument based in the HTTP RFCs not to allow this.
A payload within a GET request message has no defined semantics;
sending a payload body on a GET request might cause some existing
implementations to reject the request.
OkHttp is one of those existing implementations!
Permitting GETS to carry a semantic-free request body comes at a significant cost.
Could you explain your use case? I’ve never heard a compelling use case other than “elastic thought it would be cool LOL”.
Ah thanks - I understand the caching reason.
The thing Elastic does is not that unique I would say - sometimes being able to perform rich queries or even rich authorization structures in the body of the GET request can make an API more "developer friendly" (subjective, I know) without encoding the same information a request parameter or a header. In those cases "I'm performing a complicated query, it's in the request body" use cases, caching might be of lesser concern. I suppose that it would be reasonable behavior not to perform caching for GET requests that have a body.
One thing I don't understand here yet is why you bring up interceptors or request smuggling here, as those risks exist regardless of the HTTP method used?
Code exists that assumes GET requests don’t have a body. If that invariant is changed, this code may no longer be correct.
Interceptors: an interceptor implementing a cache (not OkHttp's built-in cache) might not pay attention to the request body field (it’s not supposed to exist!) and treat all request bodies as equivalent with respect to caching. This would be bad.
Request smuggling: you implement a Java Servlet that takes the incoming servlet request and builds an OkHttp request from it, then forwards that on to an internal webservice. Previously those internal web services never had GETs with bodies; now they do. If those things don’t attempt to read and discard the request body, then you might be able to smuggle a 2nd request through the first request’s body.
Typically OkHttp’s invariants are there to prevent developers from doing incorrect things by accident. But they have another purpose; they allow developers to assume incorrect things aren’t going to get through when they aren’t directly creating the requests. If we change the rules, then code that was relying on those rules being enforced may break.
In some ways issue #4865 is similar. Allowing OkHttp to express which local network interface is used fixes a bug, but creates the possibility for many more.
I may have misunderstood you before as you're not bringing up OkHttp specific concerns, but concerns about the surrounding ecosystem.
I respect the attitude towards the _de facto_ state of things that GET requests may be somewhat surprising. If you want to take the position that it should be OkHttp's problem to solve the general (but incorrect) expectation that GETs don't have bodies, sure. Probably the best point of view from a stability perspective.
To me personally though, it's somewhat surprising that OkHttp goes to the length it currently does. Actively breaking GET requests with bodies in OkHttp feels out of place to me when all relevant specs allow it, real world use cases exist, and as far as I know this behavior is not shared by other common HTTP clients. It effectively makes OkHttp a "subset-of-HTTP client", effectively also making it opinionated towards how servers should behave. Again - I respect you guys are making different choices than other people - but the limitation seems unexpected and artificial to me.
Yep, that’s an accurate description of the project. We don’t do the long tail of all features of every spec, but enough that makes the common stuff safe & easy. We also try hard to keep the project small and minimize dependencies.
Off the top of my head there’s a few other places where our opinions show up:
Looking at this list, it’s a lot of opinions that are shared by browsers. Which makes me wonder – can Chrome or Firefox do HTTP GETs with request bodies? That’d be something that might convince me we’re too far from the common path.
Interesting question. It seems that the XMLHttpRequest spec specifies to actively ignore any body parameters attached to a GET request. So OkHttp is in line with the XHR spec at least in this regard.
If that's a standard to get parity for, then there goes the argument. It's worth noting that this standard stems from _before_ the updates to the HTTP RFCs, but there you go.
For me it's fundamentally that OkHttp is an opionated user agent, not a toolkit that aims to supports all use cases. For example, we follow the security changes that browsers make over time, such that each upgrade potentially breaks some clients because it forces people to upgrade security. It would be easier to try to keep everything working, but sometimes it's the right thing to do to put pressure for other systems to fix.
Most helpful comment
OkHttp is an opinionated HTTP client. By constraining what we support to what the specs allow, we’re able to keep things relatively simple and offer great features like smart caching.
Elasticsearch is wrong for exposing APIs that use GET requests with bodies. They should fix their API.