apollo-android requests to express-graphql always result in http 400

958 views Asked by At

I'm having issues getting the most basic of graphQL to work when submitted via apollo-graphql to an express-graphql webapp. Via a web request through graphiql, everything works fine. As soon as I try to use apollo-android client, I get 400 errors no matter what I try.

My android dependency is:

  • com.apollographql.apollo:apollo-runtime:2.3.1

My node dependencies:

  • express:4.17.1
  • express-graphql:^0.11.0
  • graphql:^15.3.0

My basic server is:

const express = require('express')
const { graphqlHTTP } = require('express-graphql')

const {
    GraphQLSchema,
    GraphQLObjectType,
    GraphQLString,
    GraphQLList,
    GraphQLInt,
    GraphQLNonNull

} = require ('graphql')

const RootQueryType = new GraphQLObjectType({
    name: 'Query',
    description: 'Root query',
    fields: () => ({
        hello: {
            type: GraphQLString,
            resolve() {
              return 'world'
            }
        },
    })
})

const schema = new GraphQLSchema({
    query: RootQueryType
})

const app = express()

app.use('/graphql', function (req, res, next) {
    console.log("We got a request!: " + req.ip)
    next();
},
graphqlHTTP ({
    schema: schema,
    graphiql: true
}))
app.listen(5000, () => console.log('server running'))

Submitting a request via graphiQL, I'm simply requesting "{hello}" and get the successful response:

{
  "data": {
    "hello": "world"
  }
}

I generated my android schema file using the downloadApolloSchema task, and my graphiql contents are simply:

query hello() {
     hello()
 }

My main activity's onCreate():

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ApolloClient client = ApolloClient.builder().serverUrl("http://10.0.2.2:5000/graphql").build();

        client.query(
                HelloQuery.builder().build()
        ).enqueue(
                new ApolloCall.Callback<HelloQuery.Data>() {
                    @Override
                    public void onResponse(@NotNull Response<HelloQuery.Data> response) {
                        Log.d("TEST", "Hit success: " + response.toString());

                    }

                    @Override
                    public void onFailure(@NotNull ApolloException e) {
                        Log.e("TEST", "Hit on failure", e);

                    }

                    @Override
                    public void onHttpError(@NotNull ApolloHttpException e) {
                        super.onHttpError(e);
                        Log.e("TEST", "Hit on failure: " + e.message() + e.rawResponse());

                    }
                }
        );
    }

No matter what I try, and no matter how I try to get more details from either the server or the android app, the most informative stack trace I can get is:

2020-09-20 12:50:00.428 16056-16101/com.rubyengineering.graphqltutorial E/TEST: Hit on failure
    com.apollographql.apollo.exception.ApolloHttpException: HTTP 400 Bad Request
        at com.apollographql.apollo.internal.interceptor.ApolloParseInterceptor.parse(ApolloParseInterceptor.java:108)
        at com.apollographql.apollo.internal.interceptor.ApolloParseInterceptor$1.onResponse(ApolloParseInterceptor.java:53)
        at com.apollographql.apollo.internal.interceptor.ApolloServerInterceptor$2.onResponse(ApolloServerInterceptor.java:146)
        at okhttp3.RealCall$AsyncCall.execute(RealCall.java:203)
        at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
        at java.lang.Thread.run(Thread.java:764)
2020-09-20 12:50:00.429 16056-16101/com.rubyengineering.graphqltutorial E/TEST: Hit on failure: Bad RequestResponse{protocol=http/1.1, code=400, message=Bad Request, url=http://10.0.2.2:5000/graphql}

It's driving me crazy because I can't seem to dig into the 400 error any deeper, and have no idea why this is so hard. I've tried this request via an emulator as well as on an actual device. The result doesn't change obviously since it's the server throwing the error. Hopefully it's an easy error!

1

There are 1 answers

1
user1871035 On

So after hours of digging, trying to get wireshark to read the full request/response etc. I finally got it to work. Turns out that my .graphql definition file was named "Hello.graphql". As mentioned above, the contents taken from other examples were:

query hello() {
     hello()
 }

I tried removing to remove the extra parens to no avail, and I also tried to change the capitalization to no avail. One thing I missed that ended up being the fix was to remove the parens AND change the capitalization... The final working definition file contents:

query Hello {
     hello
 }