mercurius-js / mercurius-gateway

Mercurius federation support plugin
MIT License
17 stars 11 forks source link

`data` field is ignored when both `data` and `errors` are present in the service response #70

Closed OpportunityLiu closed 1 year ago

OpportunityLiu commented 1 year ago

Description

When a service returns a response containing both data and errors, the data field is ignored.

Reproduction

server.js

import Fastify from 'fastify';
import { mercuriusFederationPlugin } from '@mercuriusjs/federation';

const app = Fastify();

const schema = `
  extend type Query {
    me: User!
  }

  type User {
    id: Int!
    name: String!
    secret: String
  }
`;

const resolvers = {
    Query: {
        me: () => ({
            id: 1,
            name: 'John Doe',
        }),
    },
    User: {
        secret: () => new Error('You have no access to this field!'),
    },
};

app.register(mercuriusFederationPlugin, {
    graphiql: true,
    schema,
    resolvers,
});

app.listen({ port: 3001 });

gateway.js

import Fastify from 'fastify';
import mercuriusGateway from '@mercuriusjs/gateway';

const gateway = Fastify();
gateway.register(mercuriusGateway, {
    graphiql: true,
    gateway: {
        services: [
            {
                name: 'server',
                url: 'http://127.0.0.1:3001/graphql',
            },
        ],
    },
});

gateway.listen({ port: 3000 });

When querying the server, the result is:

{
  "data": {
    "me": {
      "id": 1,
      "name": "John Doe",
      "secret": null
    }
  },
  "errors": [
    {
      "message": "You have no access to this field!",
      "locations": [
        {
          "line": 5,
          "column": 5
        }
      ],
      "path": [
        "me",
        "secret"
      ]
    }
  ]
}

The result when querying the gateway is:

{
  "data": null,
  "errors": [
    {
      "message": "You have no access to this field!",
      "locations": [
        {
          "line": 5,
          "column": 5
        }
      ],
      "path": [
        "me",
        "secret"
      ]
    }
  ]
}

Fix

A possible fix is to modify line 98 of lib/gateway/request.js as follows:

(opts.context.errors || (opts.context.errors = [])).push(...json.errors);

This resolves the issue in the above reproduction, but I'm not sure if this is the correct fix.

mcollina commented 1 year ago

Thanks for reporting! Would you like to send a Pull Request to address this issue? Remember to add unit tests.