ardatan / ardatan/graphql-tools
Apollo BatchHttpLink queries failing in React app
- Dominant language
- TypeScript
- Stars
- 5.4k
- Forks
- 830
- Avg merge
- 10h 59m
- Merged PRs (30d)
- 45
Description
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 (
);
}
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 (
Assess!
)
}
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",
```
Contributor guide
Research direction
Start at BatchHttpLink and the reported batchHttpLink.ts:132 location, then compare its request with the working HttpLink request sent to the Express /graphql endpoint. Reproduce with the provided React and gateway examples, inspect the POST body and response, and consider the issue done when a batched query is accepted without the invalid-JSON error.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- express, graphql, javascript, react
- Domain
- api, full-stack
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 30/100