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

Getting HttpParseException when using ApolloClient with HttpCache configuration #1786

Closed
ridhi129 opened this issue Nov 19, 2019 · 12 comments · Fixed by #2107
Closed

Getting HttpParseException when using ApolloClient with HttpCache configuration #1786

ridhi129 opened this issue Nov 19, 2019 · 12 comments · Fixed by #2107
Assignees
Labels
⌛ Waiting for info More information is required

Comments

@ridhi129
Copy link

ridhi129 commented Nov 19, 2019

Summary
I am getting HttpParse Exception when I configure HttpCache in the apolloclient. Without the HttpCache setup I am able to successfully see the response.

Description
Apollo Client setup

private val apolloClient: ApolloClient by lazy {
        ApolloClient.builder()
            .serverUrl(endpoint)
            .okHttpClient(client.newBuilder().addInterceptor(interceptor).build())
            .httpCache(ApolloHttpCache(diskLruHttpCacheStore))
            .build()
    }

Request -

override fun getData(params: T, observer: Observer<Response<T.Data>>): Disposable {
    val request: ApolloCall<T.data> = apolloClient
        .query(params(some context))
        .httpCachePolicy(HttpCachePolicy.CACHE_FIRST)
    return Rx2Apollo.from(request)
        .observeOn(observeOn)
        .subscribeOn(subscribeOn)
        .subscribeObserver(observer)
}

Exception stack trace

com.apollographql.apollo.exception.ApolloParseException: Failed to parse http response
        at com.apollographql.apollo.internal.interceptor.ApolloParseInterceptor.parse(ApolloParseInterceptor.java:101)
        at com.apollographql.apollo.internal.interceptor.ApolloParseInterceptor$1.onResponse(ApolloParseInterceptor.java:53)
        at com.apollographql.apollo.internal.interceptor.ApolloServerInterceptor$2.onResponse(ApolloServerInterceptor.java:125)
        at okhttp3.RealCall$AsyncCall.run(RealCall.kt:138)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:764)
     Caused by: java.io.EOFException: End of input
        at com.apollographql.apollo.internal.json.BufferedSourceJsonReader.nextNonWhitespace(BufferedSourceJsonReader.java:946)
        at com.apollographql.apollo.internal.json.BufferedSourceJsonReader.doPeek(BufferedSourceJsonReader.java:332)
        at com.apollographql.apollo.internal.json.BufferedSourceJsonReader.beginObject(BufferedSourceJsonReader.java:169)
        at com.apollographql.apollo.response.OperationResponseParser.parse(OperationResponseParser.java:82)
        at com.apollographql.apollo.internal.interceptor.ApolloParseInterceptor.parse(ApolloParseInterceptor.java:87)
        at com.apollographql.apollo.internal.interceptor.ApolloParseInterceptor$1.onResponse(ApolloParseInterceptor.java:53) 
        at com.apollographql.apollo.internal.interceptor.ApolloServerInterceptor$2.onResponse(ApolloServerInterceptor.java:125) 
        at okhttp3.RealCall$AsyncCall.run(RealCall.kt:138) 
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) 
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) 
        at java.lang.Thread.run(Thread.java:764) 

Version
Apollo version - 1.1.1

@edenman
Copy link
Contributor

edenman commented Dec 16, 2019

I also ran into this when trying to add the Instabug http interceptor to my OkHttp instance. Can't tell if the bug is in the Instabug interceptor or the DiskLruHttpCacheStore class Instabug/Instabug-Android#259

@mrctrifork
Copy link

Reproduced today with version 1.2.3

@sav007
Copy link
Contributor

sav007 commented Jan 18, 2020

hey folks, to clarify is this issue happens when you provide custom okHttp with custom interceptor to Apollo client?

@edenman
Copy link
Contributor

edenman commented Jan 19, 2020

@sav007 exactly

@mrctrifork
Copy link

mrctrifork commented Jan 20, 2020

This is the initialization code for apollo client

imagen

And this is the OkHttpClient initialization
imagen

The .httpCache(cache) operation is missing because of the error specified on this issue

@sav007 sav007 self-assigned this Jan 29, 2020
@sav007
Copy link
Contributor

sav007 commented Jan 29, 2020

@mrctrifork is it possible to take a look at your UserAgentInterceptor, AppAuthInterceptor interceptor implementations? And another question how do you add those interceptor via addInterceptor or addNetworkInterceptor?

@mrctrifork
Copy link

Sure. I add these interceptors with addInterceptor as you can see in the lazy initializer in the last screenshot.

imagen

imagen

@sav007
Copy link
Contributor

sav007 commented Feb 10, 2020

Hey folks, sorry I couldn't reproduce this issue on any of our sample app. I tried several different combinations of OkHttp interceptors (network and application) but couldn't catch the culprit.

It could be that one of the custom interceptors closes request prematurely.

Could someone please provide a sample app (or modify existing apollo sample) where this issue is reproduced, other than that I can't really help you.

@rudas23
Copy link

rudas23 commented Mar 2, 2020

Just add this to the sample app and it will show the parse error. It's using the OkHttp standard logging interceptor. Note that .BODY is needed as level.
(Could a problem with the OkHttpLogging library)

val logInterceptor = HttpLoggingInterceptor { message ->
      Log.d("OkHttp", message)
    }.apply {
      level = HttpLoggingInterceptor.Level.BODY
    }

...
val okHttpClient = OkHttpClient.Builder()
        .addNetworkInterceptor { chain ->
          val request = chain.request().newBuilder()
              .addHeader("Authorization", "bearer ${BuildConfig.GITHUB_OAUTH_TOKEN}")
              .build()

          chain.proceed(request)
        }
        .addInterceptor(logInterceptor)
        .build()
...

// Directory where cached responses will be stored
    val file = File(applicationContext.filesDir, "apolloCache")
    // Size in bytes of the cache
    val size = 1024 * 1024.toLong()
    // Create the http response cache store
    val cacheStore = DiskLruHttpCacheStore(file, size)

    ApolloClient.builder()
        .serverUrl(baseUrl)
        .normalizedCache(sqlNormalizedCacheFactory, cacheKeyResolver)
        .okHttpClient(okHttpClient)
        .httpCache(ApolloHttpCache(cacheStore))
        .build()


@mrctrifork
Copy link

That's a really nice catch… I absolutely forgot about the logging interceptor which I have from the OkHttp dependency.

implementation "com.squareup.okhttp3:logging-interceptor:4.2.1"

Here's the instantiation:

imagen

@sav007
Copy link
Contributor

sav007 commented Mar 27, 2020

Ok, here is an update on this issue.

I finally found where is the issue, this issue happens when:

  1. When app is freshly installed (or when there is no cached response)
  2. When HttpLoggingInterceptor is added to OkHttp
  3. Log level is set to BODY

The issues is that HttpLoggingInterceptor when logging response body requests whole response https://github.com/square/okhttp/blob/master/okhttp-logging-interceptor/src/main/java/okhttp3/logging/HttpLoggingInterceptor.kt#L244-L246
that causes ApolloParseInterceptor to fail as there was a bug in our http cache: we didn't properly buffer original response, so instead of giving buffered response to ApolloParseInterceptor we give it non-buffered, that obviously will fail as response already was read from the source.

Fix is comming.

@mcossenas
Copy link

It is possible to have the latest version of the Android Apollo Client available via JCenter. Currently 1.4.1 is the only version I can see and would like at least 1.4.3 if not 1.4.4 so that I can have a fix for this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
⌛ Waiting for info More information is required
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants