Skip to content
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

method POST must have a request body. #854

Closed
crossle opened this issue May 20, 2015 · 37 comments
Closed

method POST must have a request body. #854

crossle opened this issue May 20, 2015 · 37 comments

Comments

@crossle
Copy link

crossle commented May 20, 2015

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)
@crossle
Copy link
Author

crossle commented May 21, 2015

Should the okhttp report error. https://github.com/square/okhttp/blob/master/CHANGELOG.md

@rahul-ramanujam
Copy link

I am getting the same exception , but currently I have used a workaround as per this SO post

http://stackoverflow.com/questions/30358545/caused-by-retrofit-retrofiterror-method-post-must-have-a-request-body/30358749?noredirect=1#comment48809814_30358749

@beshkenadze
Copy link

👍
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.

@crossle
Copy link
Author

crossle commented May 23, 2015

I used OkHttp 2.3.0, report this error

@beshkenadze
Copy link

@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

@RobertoArtiles
Copy link
Contributor

As a reference: square/okhttp#751

@JakeWharton
Copy link
Member

This is fixed on master by #875.

@myanimal
Copy link

myanimal commented Jun 8, 2015

@JakeWharton any idea when we'll see this fix in a release?

@Defuera
Copy link

Defuera commented Jun 9, 2015

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);

@beshkenadze
Copy link

@Defuera This is not a solution, it use POST variables instead of GET variables.

@wahidm
Copy link

wahidm commented Jun 12, 2015

Do you have an update on when a release will be available with this fix?

@JakeWharton
Copy link
Member

No. You can add an empty body yourself with @Body String body and pass an empty string as a workaround.

@viniciuscb
Copy link

same problem for me, it was working yesterday, not today anymore.

@antocara
Copy link

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"

@beshkenadze
Copy link

@anpstudio try downgrade to 2.3.0.

@IgorGanapolsky
Copy link

I am having the same problem since upgrading to Retrofit 1.9.0 (with OkHttp 2.4.0)

@ChocolateMinht
Copy link

Had the same issue with Retrofit 1.9.0 + OkHttp 2.4.0. Downgrading to OkHttp 2.3.0 temporarily resolves the issue.

@WOSHICAIXIANFENG
Copy link

compile 'com.squareup.okhttp:okhttp:2.3.0'
Error:(36, 13) Failed to resolve: com.squareup.okhttp:okhttp:2.3.0

@martin-gearzero
Copy link

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.

@dlew
Copy link
Contributor

dlew commented Sep 11, 2015

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);

@abhishek-ucreate
Copy link

downgrading to okhttp2.3 worked for me

@waqary705
Copy link

compile 'com.squareup.retrofit:retrofit:1.9.0'
Solution

include in @post Methods
@Body String anyString,

@WonderCsabo
Copy link

By extending #854 (comment) 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.

@yoganlegendkiller
Copy link

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

@vovkab
Copy link

vovkab commented Jan 8, 2016

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) 

@calren
Copy link

calren commented Jan 14, 2016

also seeing this issue in 2.7.2

@pgreze
Copy link

pgreze commented Jan 15, 2016

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 😄 )

@WonderCsabo
Copy link

@pgreze this is already fixed in the latest version.

@pgreze
Copy link

pgreze commented Jan 15, 2016

@WonderCsabo Nice! But what about 1.x releases?
Because I can't tell you when my app (or twitter-core) will migrate to retrofit2.

@WonderCsabo
Copy link

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 . :)

@efrohnhoefer
Copy link

Looks like version 1.9.0 was released Jan 7th. However, 19ac1 was merged June 2nd. The fix never made it into a 1.x release.

wmfgerrit pushed a commit to wikimedia/apps-android-wikipedia that referenced this issue Feb 19, 2016
square/retrofit#854 (comment)

Change-Id: I738c1d739e8bc871e4392b64050e7083ab72c40f
@xiaolongyuan
Copy link

+1

@piotrmoskala
Copy link

@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.

@aitbaali
Copy link

aitbaali commented Aug 14, 2016

compile 'com.squareup.okhttp:okhttp:2.3.0'works for me

@Isanderthul
Copy link

@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());

@faisalwaris
Copy link

THANKS @aitbaali and @Pixoo

@bubbleguuum
Copy link

Still an issue in 2019. Hopefully, there's the NullBodyAwareOkClient workaround posted above that works perfectly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests