web-dev-qa-db-fra.com

OKHttp lève une exception d'état non conforme lorsque j'essaie de consigner la réponse du réseau

J'ai mis l'intercepteur suivant sur mon client OkHttp:

httpClient.addInterceptor(new Interceptor() {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Response response = chain.proceed(chain.request());
        Log.d("Response", response.body().string());
        return response;
    }
    });

Cependant, cela ne joue pas bien avec Retrofit 2. Il semble que vous ne puissiez lire le flux de la réponse qu'une seule fois, ce qui pourrait être à l'origine de l'exception. Je pense que la modernisation consiste à essayer d'analyser le flux déjà analysé par le journal. Comment puis-je mettre la main sur la réponse? J'essaie actuellement de déboguer une exception JSON malformée très méchante et étrange.

C'est la trace de la pile des exceptions:

07 - 28 10: 58: 21.575 22401 - 22529 / REDACTED E / AndroidRuntime: FATAL EXCEPTION: OkHttp Dispatcher
    Process: REDACTED, PID: 22401
    Java.lang.IllegalStateException: closed
    at okhttp3.internal.http.Http1xStream$FixedLengthSource.read(Http1xStream.Java: 378)
    at okio.Buffer.writeAll(Buffer.Java: 956)
    at okio.RealBufferedSource.readByteArray(RealBufferedSource.Java: 92)
    at okhttp3.ResponseBody.bytes(ResponseBody.Java: 83)
    at okhttp3.ResponseBody.string(ResponseBody.Java: 109)
    at REDACTED.ServiceGenerator$2.intercept(ServiceGenerator.Java: 90)
    at okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.Java: 187)
    at REDACTED.ServiceGenerator$2.intercept(ServiceGenerator.Java: 89)
    at okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.Java: 187)
    at REDACTED.ServiceGenerator$2.intercept(ServiceGenerator.Java: 89)
    at okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.Java: 187)
    at REDACTED.ServiceGenerator$2.intercept(ServiceGenerator.Java: 89)
    at okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.Java: 187)
    at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.Java: 160)
    at okhttp3.RealCall.access$100(RealCall.Java: 30)
    at okhttp3.RealCall$AsyncCall.execute(RealCall.Java: 127)
    at okhttp3.internal.NamedRunnable.run(NamedRunnable.Java: 32)
    at Java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.Java: 1112)
    at Java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.Java: 587)
    at Java.lang.Thread.run(Thread.Java: 841)

Je vois qu’il ya plusieurs intercepteurs dans la pile, mais j’en ai seulement ajouté explicitement, c’est-à-dire celui qui lève l’exception.

Vous utilisez le corps de réponse dans l'intercepteur, vous allez donc vouloir créer une nouvelle réponse:

@Override public Response intercept(Chain chain) throws IOException {
  Response response = chain.proceed(chain.request());
  ResponseBody body = response.body();
  String bodyString = body.string();
  MediaType contentType = body.contentType();
  Log.d("Response", bodyString);
  return response.newBuilder().body(ResponseBody.create(contentType, bodyString)).build();
}

Vous pouvez également consulter l'intercepteur de journalisation dans le référentiel d'OkHttp: https://github.com/square/okhttp/tree/master/okhttp-logging-interceptor

26
Eric Cochran

N'appelez pas le corps de la réponse plus d'une fois, car il est lu comme un flux et n'est pas stocké en mémoire.

Vous appelez peut-être plusieurs fois answer.body (). String () car le corps de la réponse peut être énorme, donc OkHttp ne le stocke pas en mémoire, il le lit comme un flux du réseau lorsque vous en avez besoin.

Lorsque vous lisez body en tant que chaîne () OkHttp télécharge le corps de la réponse et vous le renvoie sans conserver la référence à la chaîne, il ne peut pas être téléchargé deux fois sans nouvelle demande.

https://github.com/square/okhttp/issues/1240

15
user4981235

J'ai aussi eu cette exception parce que j'ai essayé de convertir le corps de réponse 2X. J'ai d’abord consigné le response.body (). String () & puis à nouveau j’ai passé la même chose à une méthode. Ce qui causait l’exception. Vérifiez si le corps de la réponse est converti en chaîne plusieurs fois.

3
Gaurav

L'erreur est bizarre, mais le premier problème que je vois est que vous utilisez OKHTTP3 et essayez d'ajouter un générateur au client déjà créé.

Le OkHttpClient est immuable maintenant et vous devrez ajouter les intercepteurs directement à la méthode OkHttpClient.Builder en appelant addInterceptor sur le générateur .

Pour plus de clarté sur la façon de procéder, voir ceci Problème Github . Je pense que cela devrait résoudre votre problème.

0
Aashrai Ravooru