Remove ordering requirement for interface method parameters
What kind of issue is this?
- [x] 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.
Hello! First of all, thanks so much for maintaining Retrofit. It's awesome!
I ran into a hard-to-troubleshoot runtime error today caused by this exception in Retrofit:
java.lang.IllegalArgumentException: A @Path parameter must not come after a @Query. (parameter #2)
for method MyInterface.getSomething
at retrofit2.Utils.methodError(Utils.java:54)
at retrofit2.Utils.methodError(Utils.java:43)
at retrofit2.Utils.parameterError(Utils.java:64)
at retrofit2.RequestFactory.parseParameterAnnotation(RequestFactory.java:397)
at retrofit2.RequestFactory.parseParameter(RequestFactory.java:325)
at retrofit2.RequestFactory.build(RequestFactory.java:206)
at retrofit2.RequestFactory.parseAnnotations(RequestFactory.java:67)
at retrofit2.ServiceMethod.parseAnnotations(ServiceMethod.java:26)
at retrofit2.Retrofit.loadServiceMethod(Retrofit.java:202)
...
I was unable to find any information in the documentation or the code about the rationale behind that ordering requirement. I'm sure there's a good reason, but I'd like to put forth a feature request to remove that requirement if at all possible.
Ordering isn't strictly required, but it's convenient.
The reason it works this way is because the relative path of the annotation+arguments is resolved against the base URL using standard HTTP URL resolution rules which drops query params. For example, a base URL of https://example.com/foo/bar/ and a relative URL of ../baz will produce an absolute URL of https://example.com/foo/baz.
If we added a query parameter to the base URL first and got https://example.com/foo/bar/?ping=pong and then resolved the relative URL we would still end up with https://example.com/foo/baz.
Now the fix here is easy: do two passes. Do all relative URL @Path replacement first, then URL resolution, then everything else. And we could do that with a bit of added complexity.
Up until now, however, no one has complained about this so we simply forced the order to ensure we can build the URL in a single pass.
Can you give an example where needing query arguments before path arguments feels essential?
At this time, for the 2.x series, there are no plans to remove this. One complain in 10 years isn't bad. Happy to reconsider for future major versions where we change strategy (and hopefully push more responsibility into OkHttp for URL building).