31

I am using Retrofit to make api calls in my android application. I have to submit a @Body of JSON

@GET("api/")
void getData(@Body UserPostRequestBody request)

I get error message

retrofit.RetrofitError: apiCall: Non-body HTTP method cannot contain @Body or @TypedOutput.

Have you any idea?

user2026760
  • 429
  • 1
  • 4
  • 5
  • 9
    You need to change the annotation to @POST – Tarun Apr 23 '15 at 22:08
  • 3
    @user2026760, do you have to use a GET request with a body? If you do, you can create your own annotation and have it handle a body in the get request. Not ideal, but I am sure someone, somewhere, has created a server that does that. I have had to supply a body with a DELETE request, which I hate to do; but I have done them. – Ray Hunter Dec 06 '15 at 08:05
  • 1
    How can i create a custom annotation? – ragar90 Nov 15 '19 at 19:10

6 Answers6

18

To send data along with your Get Request you can do the following:

//sending data as a url parameter
@GET("/group/{id}/users")
List<User> groupList(@Path("id") int groupId);

as said in this SO answer, Server semantics for GET, however, are restricted such that a body, if any, has no semantic meaning to the request- Roy Fielding.

Community
  • 1
  • 1
harshitpthk
  • 3,766
  • 2
  • 21
  • 30
15

The definition of GET as explained here in this answer explains that a body isn't supposed to mean anything, so Retrofit doesn't allow you to add a body. That said, it is not true that a server HAS to follow this format. It's entirely possible for a server to have a GET endpoint that not only takes, but REQUIRES a body. It would be "bad" architecture, but it seems a bit silly for Retrofit to limit what the library can do unnecessarily.

Furthermore, the various HTTP methods have different definitions for what they are SUPPOSED to do. For example a GET gets information, a POST creates a new entry/object by providing information to the server, a PUT updates an existing entry/object etc. The problem is, the easiest way to pass complex data to the server, especially when using retrofit, is by using JSON. So the ideal way to GET information from the server while providing a complex filter would be to send a JSON body along with the GET request. Unfortunately, there is no HTTP request method that allows for this under the spec.

Community
  • 1
  • 1
Guybrush
  • 331
  • 2
  • 8
  • 1
    Totally agree with you @Guybrush. And because that restriction, our option when we need to send complex data to GET information from the server, is break the REST convention and start to use POST. – Nilton Vasques Oct 26 '17 at 14:56
  • And how do i work arround the restriction from retrofit? is there a way to override it? – ragar90 Dec 11 '19 at 16:43
5

This error also occurs when API required @POST and you are using @GET

Akash Bisariya
  • 2,431
  • 1
  • 24
  • 39
satyender
  • 617
  • 2
  • 9
  • 20
0

If the request body you need to send is not to complex you can also specify the query parameters as https://myserverdomain.com?somebody[property1]=value specifically on retrofit you define it like this:

Observable<Response<SomeClass>> someMethod(@Query("somebody[property1]") int property1);

That will work at least if you are requesting to a rails server hope this answer helps somebody

marc_s
  • 675,133
  • 158
  • 1,253
  • 1,388
ragar90
  • 70
  • 7
0
  • GET call doesnt accept body use Query("key") or Path("key")

  • only POST method accepts Body @POST("api/") void getData(@Body UserPostRequestBody request)

-3

To Send body in a GET request use:

@HTTP(method = "GET", path = "api/users", hasBody = true)
Observable<JobDeleteResponseModel> jobDelete(@Body UserPostRequestBody body);

as is described in this post

eriknyk
  • 161
  • 1
  • 5
  • 1
    Put **hasBody = true** to GET method will produce error: method GET must not have a request body – azwar_akbar Sep 06 '19 at 13:25
  • by using `@HTTP and hasBody = true` is just preventing from the exception but still it is showing the same error `method GET must not have a request body` – Sumit Jain Sep 17 '19 at 09:59