Skip to content

Apollo BatchHttpLink queries failing in React app #4280

@dsbw

Description

@dsbw

Upgrading an old Apollo client/server setup to use graphql-tools exclusively, BatchHttpLink queries fail with "POST body sent invalid JSON" (network error) and "POST http://localhost:4000/graphql 400 (Bad Request) batchHttpLink.ts:132" (on the console).

We tried a sandbox but it didn't like the apollo imports. :-/

To reproduce, create a basic create-react-app. We have this for our initialization:

import { BatchHttpLink } from "@apollo/client/link/batch-http"
import {
  ApolloClient,
  InMemoryCache,
  ApolloProvider,
  ApolloLink,
  useQuery,
  gql
} from "@apollo/client";
import Assess from './assess'


const link = ApolloLink.from([
  new BatchHttpLink({uri: '[http://localhost:4000/graphql'](http://localhost:4000/graphql%27)})
])


const client = new ApolloClient({
  link,
  cache: new InMemoryCache()
});

function App() {

  return (
    <ApolloProvider client={client}>
      <Assess />  
    </ApolloProvider>
  );
}

export default App;

And we have this for a query page. (It doesn't really seem to matter what query is made or whether it exists on the server.)

import React from 'react'
import {
  useQuery,
  gql
} from "@apollo/client";


const ome_client_assessments = gql`
  query ome_client_assessments($uuid: ID!) {
    client_assessments(uuid: $uuid) {
      id
      name
    }
  }
`

const Assess = () => {
  const { loading, error, data } = useQuery(ome_client_assessments, {
    variables: { user: '12345' }
  })
  return (
    <h1>Assess!</h1>
  )
}

export default Assess

On the backend, we've taken our server (which normally stitches together a bunch of schema based on environment variable settings) and hard-coded a single service. Again, it doesn't seem to matter what this points to because it never gets this far:

const waitOn = require('wait-on');
const express = require('express');
const cors = require('cors');
const {graphqlHTTP} = require('express-graphql');
const {introspectSchema} = require('@graphql-tools/wrap');
const {stitchSchemas} = require('@graphql-tools/stitch');
const {fetch} = require('cross-fetch');
const {print} = require('graphql');

const service_map = {'accounts': {"link": 'http://localhost:3000/graphql'}}

function makeRemoteExecutor(url) {
    return async ({document, variables, context}) => {
        const query = typeof document === 'string' ? document : print(document);
        const fetchResult = await fetch(url, {
            method: 'POST',
            headers: {
                'Auth': context.authHeader,
                'Content-Type': 'application/json',
                "x-api-token": '2ade0bbe320ed0529cec2cfc9f224f57',
            },
            body: JSON.stringify({query, variables}),
        });
        return fetchResult.json();
    };
}

async function makeGatewaySchema() {
    const submap = []
    for (const key in service_map) {
        let executor = makeRemoteExecutor(service_map[key]['link'])
        submap.push({
            schema: await introspectSchema(executor, {}),
            batch: true, //Not sure if this actually does anything...
            executor: executor
        })
    }

    return stitchSchemas({
            subschemas: submap,
        }
    );
}

waitOn({resources: []}, async () => {
    const schema = await makeGatewaySchema();
    const app = express();
    app.use(cors());
    app.use('/graphql', graphqlHTTP((req) => ({
        schema,
        context: {authHeader: req.headers.auth},
        graphiql: {headerEditorEnabled: true},
    })));
    app.listen(4000, () => console.log('gateway running at http://localhost:4000/graphql'));
});

If we use a regular HttpLink on the client, our code works (or returns the expected errors from the service), whereas BatchHttpLink gives us the "POST body sent invalid JSON" error.

These behaviors show up when everything is running on a single Mac, PC or in a kubernetes pod hosted on AWS. Node versions are 12, 15 and 16. React version is 17.0.2 and create-react-app is 5.0.0. Using these graphql libraries:

   "@graphql-tools/batch-delegate": "^8.2.4",
    "@graphql-tools/delegate": "^8.5.0",
    "@graphql-tools/schema": "^7.0.0",
    "@graphql-tools/stitch": "^7.0.4",
    "@graphql-tools/wrap": "^7.0.1",

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions