retrofit icon indicating copy to clipboard operation
retrofit copied to clipboard

Bug : Problem with response body, not parsing body if response is 202

Open mangeshsambare opened this issue 5 years ago • 6 comments

I know that Retrofit does not allow the Call without any return types, developer should have to add some object in return type like

@GET
 Call<Response<JsonObject>> checkStatus(@Url String url);

Above is client application request checking status of data. In this request, client app gets two types of different responses 200 success with body & 202 accepted without body. Client app have to call this request with an interval of 5 or n seconds whenever in response client app gets 202 accepted response. If other than 202 it gets different status code then client app stops this calling this request.

So in this case, client app accept return type of Response<JsonObject> In 202 accepted response there is no body. So it is gives error :

Retrofit2 error java.io.EOFException: End of input at line 1 column 1

I changed this Response<JsonObject> to Response<Object> & Response<String>, but still gives same above error.

So I solved this issue by changing return type of request from Response<JsonObject> to Response<Void> as it is suggested here

@GET
 Call<Response<Void>> checkStatus(@Url String url);

Now above request is working fine for 202 accepted response. But not working when client app gets 200 success response & in that response server sends body in it. In Response object app can not gets body because of return type Void.

In above request of return type I use Response object like Call<Response>. I use this object because client app needs to check HTTP status code like 200, 202 etc. I changed from Call<Response> to Call<ResponseBody> but it does not return status code. Only Call<Response> object returns HTTP status code.

In same request, how can I handle null/empty body if I get 202 accepted status code & body data if I get 200 success status code?

I know that, Retrofit does not allow Call without type like Call<Response<Void>> or Call<Response<JsonObject>> and is not able to map empty body, but what if one of developer have above use case? How can it will be solve? I don't know about any standardization of accepting body only if 200 & not in 202, is there any standard way to do this?

mangeshsambare avatar Jan 08 '20 08:01 mangeshsambare

I through modify converter solved this problem. For example,i modify the JacksonResponseBodyConverter so when server not return response body the converter return a default value:

  @Override
  public T convert(ResponseBody value) throws IOException {
    try {
      if (value.contentLength() == 0) {
        return (T) new Object();
      }
      return adapter.readValue(value.charStream());
    } finally {
      value.close();
    }
  }

I test it and works well,but I don't know other people need it or not?

ctlove0523 avatar May 21 '20 15:05 ctlove0523

I've write test scenario in CallTest.java, but it passed. This commit link is here.

I would like you help me to reconstruct your case, so that one can help you to solve this issue.

zjc17 avatar May 30 '20 13:05 zjc17

@Jiachen-Zhang Thanks for your help. I gone through your code. In your test case you set body empty string. server.enqueue(new MockResponse().setResponseCode(202).setBody(""));

Instead of empty body just try null means Void. You will get error. From server my application get null body & response is 202 and it is successfully works with other client application like iOS, Java SpringBoot.

Please do send null in body

mangeshsambare avatar Jun 01 '20 05:06 mangeshsambare

hey @mangeshsambare did you figure this out? just bumped into something similar and i've tried a few different approaches:

  • using Call<Void>,
  • using Call<ResponseBody>,
  • using a custom Converter.Factory, like the NullOnEmptyConverterFactory you'll find here.

unfortunately no luck yet, i'd appreciate some help.

BMarton avatar Nov 04 '20 18:11 BMarton