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

DELETE with Body in Retrofit 1.5.0 #458

Closed
cesards opened this issue Apr 8, 2014 · 16 comments
Closed

DELETE with Body in Retrofit 1.5.0 #458

cesards opened this issue Apr 8, 2014 · 16 comments

Comments

@cesards
Copy link

cesards commented Apr 8, 2014

Hi,

First of all, I know that including body in DELETE request is bad, but I'm working for a customer with a legacy API, so I can't avoid it.

I'm getting this error (and the app stops):

Non-body HTTP method cannot contain @Body or @TypedOutput.

I've been having look to other responses:

#330
#426

But neither of them worked for me with Retrofit 1.4.1

If I use my custom DELETE annotation:

@Documented
@Target(METHOD)
@Retention(RUNTIME)
@RestMethod(value = "DELETEWITHBODY", hasBody = true)
public @interface DELETEWITHBODY {
  String value();
}

I get the next error (and the app doesn't stop):

Expected one of [OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, PATCH] but was DELETEWITHBODY

Is there any kind of dirty solution for now?

Thanks in advance!

@JakeWharton
Copy link
Member

Can you paste the full stack trace? I suspect the HTTP client you are using is being overly strict.

@cesards
Copy link
Author

cesards commented Apr 9, 2014

Yep sorry, I forgot posting the full stack strace.

Trace (cause & detailMessage from Retrofit) using custom annotation:

java.net.ProtocolException: Expected one of [OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, PATCH] but was DELETEWITHBODY

Trace using DELETE:

04-09 02:40:23.237  FATAL EXCEPTION: Retrofit-Idle
    java.lang.IllegalArgumentException: UserManagementService.unsubscribeToNewsletter: Non-body HTTP method cannot contain @Body or @TypedOutput.
            at retrofit.RestMethodInfo.methodError(RestMethodInfo.java:118)
            at retrofit.RestMethodInfo.parseParameters(RestMethodInfo.java:435)
            at retrofit.RestMethodInfo.init(RestMethodInfo.java:129)
            at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:329)
            at retrofit.RestAdapter$RestHandler.access$100(RestAdapter.java:264)
            at retrofit.RestAdapter$RestHandler$2.obtainResponse(RestAdapter.java:315)
            at retrofit.CallbackRunnable.run(CallbackRunnable.java:42)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
            at retrofit.Platform$Android$2$1.run(Platform.java:142)
            at java.lang.Thread.run(Thread.java:841)

For having more info, heere is my service call:

RestAdapter restAdapter = new RestAdapter.Builder().setEndpoint(Config.BASE_URL + Config.API_VERSION)
                .setClient(new CustomClient(new OkClient(), context))
                .build();

where CustomClient is:

public class CustomClient implements Client {

  private final ConnectivityManager connectivityManager;
  private Client wrappedClient;

  public CustomClient(Client wrappedClient, Context context) {
    this.wrappedClient = wrappedClient;
    connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
  }

  @Override public Response execute(Request request) throws IOException {
    final NetworkInfo activeNetwork = connectivityManager.getActiveNetworkInfo();
    final boolean isConnected = activeNetwork != null && activeNetwork.isConnectedOrConnecting();
    if (!isConnected) {
      throw new NetworkFailureException();
    }
    return wrappedClient.execute(request);
  }
}

@cesards
Copy link
Author

cesards commented May 12, 2014

@JakeWharton Are you planning support this in future versions?

Thank you mate!

@JakeWharton
Copy link
Member

This is a limitation by the HTTP client, not Retrofit. OkHttp version 2.0 will fix this and I'm not sure as to whether the Apache client supports this or not. We won't be able to make this work for HttpUrlConnection.

@cesards
Copy link
Author

cesards commented May 23, 2014

Thx!

On 22 May 2014 23:34, "Jake Wharton" notifications@github.com wrote:

Closed #458.

—hu
Reply to this email directly or view it on GitHub.

@deionalims
Copy link

Hi,

I don't get it. I'm using RetroFit 1.6.0 and okhttp 2.0.0-RC2 and I'm still having the error:
Non-body HTTP method cannot contain @Body or @TypedOutput.
I'm using DELETE with a body.

Yet the issue #605: "Allow DELETE Request Body, Ensure Sane Behavior" is marked as fixed on the okhttp git repository.

Am I missing something ?

Thanks

@JakeWharton
Copy link
Member

Retrofit's @DELETE doesn't support a request body because the HTTP spec says there shouldn't be one. If you need to use a body with the DELETE method you will need to create your own HTTP annotation as mentioned above.

@deionalims
Copy link

Which I did and it works fine.
Thanks.

@farmazon3000
Copy link

Retrofit's @delete doesn't support a request body because the HTTP spec says there shouldn't be one.

Which HTTP spec says there shouldn't be one?

@darshanz
Copy link

darshanz commented Jan 7, 2016

There is nothing in the specs that strictly prevent us from implementing DELETE with body. Retrofit should be flexible too.

@thibaultmeyer
Copy link

The response is on the HTTP 1.1 RFC (http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.7)

A successful response SHOULD be 200 (OK) if the response includes an entity describing the status, 202 (Accepted) if the action has not yet been enacted, or 204 (No Content) if the action has been enacted but the response does not include an entity.

The DELETE method could return a message but isn't mandatory

@Zhuinden
Copy link

@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@RestMethod(value = "DELETE", hasBody = true)
public @interface RetrofitDeleteWithBody {
    String value();
}

This worked for me, just use it like a normal DELETE except it actually works with a body!
Retrofit 1.9.

@rchampa
Copy link

rchampa commented Jun 29, 2016

I'm using

compile 'com.google.code.gson:gson:2.5'
compile 'com.squareup.retrofit2:retrofit:2.0.2'
compile 'com.squareup.retrofit2:converter-gson:2.0.2'
compile 'com.squareup.okhttp3:okhttp:3.0.1'

But cannot find symbol RestMethod

@kherembourg
Copy link

With Retrofit 2 the solution is to use the HTTP interface instead of DELETE.
So replace :

@DELETE("my/path")

By

@HTTP(method = "DELETE", path = "/my/path", hasBody = true)

I would like to create my own interface DELETE_BODY but I didn't find how yet since like you said RestMethod is not available anymore.

@PiaDeveloperBr
Copy link

Delete method is not working. In my case I use:
@delete("/Stories/{storyid}")
Call deleteStory(@path("storyid") int storyId);

But its not working :( Please Help me out... !!

@liuguangmao
Copy link

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