简体   繁体   中英

GraphQL how to handle an error message when the response originates from a microservice

I have an API that when an invalid authorization token is passed in it responds like so:

Unauthorized response:

{
   "status": "failure",
   "message": "Unauthorized" 
}

But when a valid token is passed in, it will respond with an array of objects, with each object representing a document like so:

Authorized response:

[{
    "_id": "5bd8f520e68ba2003ec9f528",
    "user": "5bd8f50cced689002769d254",
    "title": "A title for a document",
    "content": "Some content for a document",
}, { 
    "_id": "5bd8f520e68ba2003ec9f528",
    "user": "5bd8f50cced689002769d254",
    ....
}]

How do i gracefully handle error responses in GraphQL when they originate from my microservices running express? and how do i cover the change in data structure within the response?

My resolver:

const getDocuments = async context => {
  const config = {
    headers: {
      Authorization: context.token
    }
  };

  try {
    return await axios
      .get("http://document_service:4000/v1/documents", config)
      .then(response => {
        return response.data;
      })
      .catch(error => {
        return error.data;
      });
  } catch (err) {
    return err;
  }
};

const Query = {
  docServiceGetDocs: (obj, args, context) => getDocuments(context)
};

response.data will return either an array of documents or an object with a status and message.

My schema:

type getDocuments {
  _id: String
  user: String
  title: String
  content: String
}

type Query {
  docServiceGetDocs: [getDocuments]
}

[getDocuments] I suppose this expects an array of objects, but unsure of how to handle if i get the unauthorized response as an object.

I am using apollo server 2

Ideally, the API's response would have a somewhat consistent shape, regardless of status, if the content response is used to communicate errors instead of the status code.

{
   "status": "failure",
   "message": "Unauthorized",
   "response": []
}

{
   "status": "success",
   "message": "",
   "response": [{ user: "Dan" }],
}

But if that's not easily fixed, you can just check the shape of the response inside your resolver:

const getDocuments = async context => {
  const config = {
    headers: {
      Authorization: context.token
    }
  };

  try {
    const response = await axios.get("http://document_service:4000/v1/documents", config)
    const data = response.data
    if (data && data.status === 'failure') {
      throw new Error(data.message)
    }
    return data
  } catch (err) {
    // example of how to handle axios errors

    let message = ''
    if (err.response) {
      // Status code out of the range of 2xx, format error message according
    } else if (err.request) {
      // The request was made but no response was received, format message accordingly
    } else {
      message = err.message
    }
    // throw whatever error you have so it's included in your graphql response
    throw new Error(message) 
  }
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM