0
votes

I have an Apollo GraphQL client running in react native. It connects to a lambda instance running graphQL. My problem is that I am trying to send a mutate request to the server (have not setup queries yet), and the server is getting the following and declaring a syntax error(Expected Name, found String \"operationName\").

When I was testing the graphQL server, the requests looked like the ones specified below. Is Apollo Client not formatting the requests properly (if so why not) or is it functioning as intended?

Body sent from Apollo client to graphQL lambda:

{
"operationName": "createUser",
"variables": {
    "firstName": "Jane",
    "lastName": "Doe",
    "email": "[email protected]",
    "username": "jane_doe.com",
    "provider": "none"
    "jwt": "none"
},
"query": "mutation createUser($firstName: String!, $lastName: String!, $email: String!, $username: String!, $provider: String, $jwt: String!) { 
createUser(firstName: $firstName, lastName: $lastName, email: $email, username: $username, provider: $provider, jwt: $jwt) {
    createdAt
    __typename
}
}"}

A Normal request that works from Postman.

mutation {
  createUser(firstName: "Jane", lastName: "Doe", email: "[email protected]", username: "jane_doe.com", jwt: "none", provider: "none") {
    firstName
  }
}

Code from react-native app

// The mutation in the render function
<Mutation mutation={createUserMutation}>
  {(createUser, error) => {
    console.log('error-----------', error);
    // If there is an error throw the error
    if (error) {
      console.log('error----------', error);
    }
    if (createUser) {
      // If the response has data load the response data via the createPlayer property.
      return (
        <LoginButton
          onPress={() => {
            this.signIn(createUser);
          }}
        />
      );
    }

    // By default it is loading the result so just return loading...
    return <Text>Loading...</Text>;
  }}
</Mutation>

// The signin function called when the user presses the login button
async signIn(createUser) {
  ...
  try {
    Auth.signIn(un, password)
      .then(data => {
        ...
        this.createUserFunc(
          createUser,
          'Jane',
          'Doe',
          '[email protected]',
          'jane_doe.com',
          'none',
          'none'
        );
   }
   ...
}

// The create user function called from the signin function
createUserFunc = (func, firstName, lastName, email, username, provider, jwt) => {
  const newUser = {
    firstName,
    lastName,
    email,
    username,
    provider,
    jwt,
  };
  func({variables: newUser});
};

// The gql syntax mutation
const createUserMutation = gql`
  mutation createUser(
    $firstName: String!
    $lastName: String!
    $email: String!
    $username: String!
    $provider: String
    $jwt: String!
  ) {
    createUser(
      firstName: $firstName
      lastName: $lastName
      email: $email
      username: $username
      provider: $provider
      jwt: $jwt
    ) {
      createdAt
    }
  }
`;
1
Does the same mutation work if you send it through a different client like GraphiQL, GraphQL Playground, Postman or Altair (or just a plain curl command)? If the request doesn't work regardless of client, that would point at a problem with the server not the client.Daniel Rearden
@DanielRearden Thanks for the info. I didn't know that there were tools like GraphiQL out there. I figured out the problem is with the server... Now to investigate...Reid
Ahh... More things are becoming clear. A GQL POST request is formatted far differently than a GET request. My server side relies on me sending GET formatted requests (although in Postman, I was posting). Now to figure out how to make my server interpret POST formatted GQLReid
If you're not already, I would suggest implementing your endpoint using apollo-server-lambda rather than trying to work with the core library directly.Daniel Rearden
@DanielRearden I got it working right with apollo-server-lambda. So much easier than using the core library! Thank you so much!!!Reid

1 Answers

2
votes

Most GraphQL servers that accept requests over HTTP are listening to two different types of content (indicated with the Content-Type header): application/graphql and application/json. You server seems to only listen to requests with a application/graphql body.

The problem with Content-Type: application/graphql is that GraphQL execution consist out of up to three parameters that can be supplied by the client:

  1. The query (required)
  2. The variable values of the query
  3. The operation name

This enables query documents to be entirely static. But if the content of the request is only the GraphQL query, the other parameters need to go somewhere else. In theory they could be supplied as GET parameters but usually all clients use the JSON format to supply all three as outlined here.

As Daniel has pointed out you can use a GraphQL server implementation for your framework/technology of choice to handle that for you. Alternatively you would have to react to the header of the request yourself (which could be a good exercise but you are probably going to miss an edge case that the library authors have thought of).