使用Retrofit进行带请求体的HTTP GET请求

36

我正在使用Retrofit在Android应用程序中进行API调用。我必须提交一个JSON的@Body。

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

我收到错误信息

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

你有什么想法吗?


11
你需要将注释更改为 @POST。 - Tarun
3
@user2026760,你需要使用带有请求体的GET请求吗?如果是这样,你可以创建自己的注释,并使其处理GET请求中的请求体。虽然不是理想方法,但我相信某个人在某个地方已经创建了一个可以实现这个功能的服务器。我曾经不得不在DELETE请求中提供请求体,尽管我不喜欢这样做,但我还是这样做了。 - Ray Hunter
1
我该如何创建自定义注解? - ragar90
6个回答

20

如此解释,GET方法不应该包含请求体,因此Retrofit不允许添加请求体。但是,服务器并不一定要遵循这个规范。服务器完全可以拥有一个GET端点,并且不仅接受请求体,而且要求请求体。尽管这样的架构不够优秀,但是限制Retrofit的功能似乎有些无谓。

此外,不同的HTTP方法有着不同的定义。例如,GET用于获取信息,POST通过向服务器提供信息创建新条目/对象,PUT用于更新现有的条目/对象等。问题在于,传递复杂数据到服务器的最简单方式,特别是使用Retrofit时,是使用JSON。因此,在提供复杂过滤器的同时从服务器获取信息的理想方式是发送带有JSON请求体的GET请求。不幸的是,根据规范,没有HTTP请求方法允许这样做。


1
完全同意你的看法,@Guybrush。由于这种限制,当我们需要发送复杂数据以获取服务器信息时,我们的选择是打破REST约定并开始使用POST。 - Nilton Vasques
我该如何解决Retrofit的限制?有没有办法覆盖它? - ragar90
作为客户端,我们应该如何强制服务器端点使用POST而不是GET? Retrofit有没有解决这个限制的方法,或者我需要为此(些)特定端点使用另一个客户端? - Alexander Petrovskiy
根据@Guybrush提供的链接,更新说明该规范自2014年起已过时,并提到“一些旧实现可能会拒绝带有正文的GET请求”。 - Alexander Petrovskiy

19

要在Get请求中发送数据,您可以采取以下措施:

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

正如在这个答案中所说的那样,GET方法对于服务器的语义是受限制的,因此,如果有请求体(request body),也没有语义上的意义- Roy Fielding。


谢谢您的回答。我刚刚将我的方法更改为POST,它起作用了。 - Pedro Machado

6
这个错误也会在API需要 @POST,而你使用了 @GET 时出现。

0
  • GET调用不接受请求体,请使用Query("key")Path("key")

  • 只有POST方法接受请求体 @POST("api/") void getData(@Body UserPostRequestBody request)


0
如果您需要发送的请求正文不是太复杂,您也可以将查询参数指定为https://myserverdomain.com?somebody[property1]=value。特别是在Retrofit中,您可以这样定义它:
Observable<Response<SomeClass>> someMethod(@Query("somebody[property1]") int property1);

如果你正在请求Rails服务器,那么这个方法至少可以工作。希望这个答案能帮到某些人。


-7

使用GET请求发送正文的方法:

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

文章所述


2
hasBody = true 添加到 GET 方法中会产生错误:GET 方法不应该有请求正文。 - azwar_akbar
通过使用@HTTPhasBody = true仅仅是防止异常发生,但仍显示相同的错误method GET must not have a request body - Sumit Jain

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接