Why?
compile 'com.squareup.okhttp:okhttp:2.3.0'
compile 'com.squareup.retrofit:retrofit:1.9.0'
D java.lang.IllegalArgumentException: method POST must have a request body.
D at com.squareup.okhttp.Request$Builder.method(Request.java:236)
D at retrofit.client.OkClient.createRequest(OkClient.java:59)
D at retrofit.client.OkClient.execute(OkClient.java:53)
D at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:326)
D at retrofit.RestAdapter$RestHandler.access$100(RestAdapter.java:220)
D at retrofit.RestAdapter$RestHandler$2.obtainResponse(RestAdapter.java:278)
D at retrofit.CallbackRunnable.run(CallbackRunnable.java:42)
D at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
D at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
D at retrofit.Platform$Android$2$1.run(Platform.java:142)
D at java.lang.Thread.run(Thread.java:818)
Should the okhttp report error. https://github.com/square/okhttp/blob/master/CHANGELOG.md
I am getting the same exception , but currently I have used a workaround as per this SO post
:thumbsup:
Here is changes: https://github.com/square/okhttp/blob/master/okhttp/src/main/java/com/squareup/okhttp/Request.java#L244
Temporary solution: downgrade OkHttp to version 2.3.0.
I used OkHttp 2.3.0, report this error
@crossle Maybe the dependencies was getting a newer version of the library.
In 2.3 there is no checking: https://github.com/square/okhttp/blob/parent-2.3.0/okhttp/src/main/java/com/squareup/okhttp/Request.java#L236
As a reference: https://github.com/square/okhttp/issues/751
This is fixed on master by #875.
@JakeWharton any idea when we'll see this fix in a release?
I solved this issue by replacing @Query to @Field, heres how:
Not working code:
@POST("/my/url/path")
Result postToServer(
@Query("user_name") String userName);
Working example:
@FormUrlEncoded
@POST("/my/url/path")
Result postToServer(
@Field("user_name") String userName);
@Defuera This is not a solution, it use POST variables instead of GET variables.
Do you have an update on when a release will be available with this fix?
No. You can add an empty body yourself with @Body String body and pass an empty string as a workaround.
same problem for me, it was working yesterday, not today anymore.
compile 'com.squareup.retrofit:retrofit:1.9.0'
compile 'com.squareup.okhttp:okhttp:2.4.0'
Today same problem, but the solution of Jake all ok, "@Body String body"
@anpstudio try downgrade to 2.3.0.
I am having the same problem since upgrading to Retrofit 1.9.0 (with OkHttp 2.4.0)
Had the same issue with Retrofit 1.9.0 + OkHttp 2.4.0. Downgrading to OkHttp 2.3.0 temporarily resolves the issue.
compile 'com.squareup.okhttp:okhttp:2.3.0'
Error:(36, 13) Failed to resolve: com.squareup.okhttp:okhttp:2.3.0
This is still an issue in 2.5.0:
compile 'com.squareup.okhttp:okhttp-urlconnection:2.5.0'
compile 'com.squareup.okhttp:okhttp:2.5.0'
compile 'com.squareup.retrofit:retrofit:1.9.0'
Curiously the OkHttp changelog for v2.4.0 says:
_• "Fix: OkApacheClient now allows an empty PUT and POST."_
This seems to be the version in which the error started since v2.3.0 works fine.
The workaround is to use an empty body, but using @Body String empty wasn't working for me due to using a Gson converter. As a result, it was literally sending "" (i.e., two characters) instead of nothing.
The solution was to use a TypedOutput as the body. I setup this empty output:
class EmptyOutput implements TypedOutput {
public static final TypedOutput INSTANCE = new EmptyOutput();
private EmptyOutput() { }
@Override
public String fileName() {
return null;
}
@Override
public String mimeType() {
return "application/json";
}
@Override
public long length() {
return 0;
}
@Override
public void writeTo(OutputStream out) throws IOException {
}
}
Then I can use it in the method signature:
@POST("/some/url)
Observable<Thing> doThing(@Body TypedOutput empty);
Then I call it using my instance:
service.doThing(EmptyOutput.INSTANCE);
downgrading to okhttp2.3 worked for me
compile 'com.squareup.retrofit:retrofit:1.9.0'
Solution
include in @Post Methods
@Body String anyString,
By extending https://github.com/square/retrofit/issues/854#issuecomment-139658149 solution, you can create the following client:
package your.package;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.internal.http.HttpMethod;
import java.io.IOException;
import java.io.OutputStream;
import retrofit.client.OkClient;
import retrofit.client.Request;
import retrofit.client.Response;
import retrofit.mime.TypedOutput;
/**
* Workaround for https://github.com/square/retrofit/issues/854 .
*/
public class NullBodyAwareOkClient extends OkClient {
public NullBodyAwareOkClient() { }
public NullBodyAwareOkClient(OkHttpClient okHttpClient) {
super(okHttpClient);
}
@Override
public Response execute(Request request) throws IOException {
if (HttpMethod.requiresRequestBody(request.getMethod()) && request.getBody() == null) {
Request newRequest = new Request(request.getMethod(), request.getUrl(), request.getHeaders(), EmptyOutput.INSTANCE);
return super.execute(newRequest);
}
return super.execute(request);
}
private static class EmptyOutput implements TypedOutput {
static final TypedOutput INSTANCE = new EmptyOutput();
private EmptyOutput() { }
@Override
public String fileName() {
return null;
}
@Override
public String mimeType() {
return "application/json";
}
@Override
public long length() {
return 0;
}
@Override
public void writeTo(OutputStream out) throws IOException {
}
}
}
Then use it in your RestAdapter.Builder:
new RestAdapter.Builder()
.setClient(new NullBodyAwareOkClient())
// ...
This way you can get rid of the dummy @Body parameters in your API methods.
Am using retrofit 1.9.0 along with okhttp 2.4.0 is there any default json converter for retrofit 1.9 am making async call in interface but when in try to implement it throws service method cannot return void don't know where am doing mistake
Still reproduceable in 2.7.2:
compile 'com.squareup.okhttp:okhttp:2.7.2'
compile 'com.squareup.okhttp:okhttp-urlconnection:2.7.2'
compile 'com.squareup.retrofit:retrofit:1.9.0'
Caused by: java.lang.IllegalArgumentException: method POST must have a request body.
at com.squareup.okhttp.Request$Builder.method(Request.java:259)
at retrofit.client.OkClient.createRequest(OkClient.java:59)
at retrofit.client.OkClient.execute(OkClient.java:53)
at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:342)
at retrofit.RestAdapter$RestHandler.invoke(RestAdapter.java:251)Â
also seeing this issue in 2.7.2
I don't understand: this bug is very old, seems closed but still in the latest version.
This problem has broken many libraries (like twitter-core) and many developers are probably stuck with an old version.
Could you reopen the issue or explain this breaking change in public API?
(Thanks for your answer and this wonderful library :smile: )
@pgreze this is already fixed in the latest version.
@WonderCsabo Nice! But what about 1.x releases?
Because I can't tell you when my app (or twitter-core) will migrate to retrofit2.
Well that fix was added before changing the version to 2.x, so it is possible, but only @JakeWharton and @swankjesse can know they want to release an update for 1.x or not . :)
+1
@Body String emptyBody wasn't working for me as backend server I was working with, was returning Bad request and not accepting empty string as a body.
I've just sent empty JSON instead of empty String
@POST("/some/url)
Observable<Thing> doThing(@Body JsonElement empty);
and then I just called my method like this:
doThing(new JsonObject());
Hope it will help if some of users have similar problem.
compile 'com.squareup.okhttp:okhttp:2.3.0'works for me
@pixoo I did as you suggested, thank you, it was the easiest solution. Just a note that on using JsonObject, but I needed to use @Body JsonObject empty
@POST("reports/{report_id}")
Call<APISuccess> resendUserReportById(@Path("report_id") String var1, @Body JSONObject empty);
and then
Call<APISuccess> request = reportsApi.resendUserReportById(intentReportId,new JSONObject());
THANKS @aitbaali and @pixoo
Still an issue in 2019. Hopefully, there's the NullBodyAwareOkClient workaround posted above that works perfectly.
Most helpful comment
I don't understand: this bug is very old, seems closed but still in the latest version.
This problem has broken many libraries (like twitter-core) and many developers are probably stuck with an old version.
Could you reopen the issue or explain this breaking change in public API?
(Thanks for your answer and this wonderful library :smile: )