我在应用程序中使用graphql,并且错误地发送了以下响应。
您可能已经注意到graphql将所有错误发送为状态码200。我从API返回的错误位于data.errors
下。
{
"data": {
"errors": [
{
"message": "Error: Token has expired",
"locations": [
{
"line": 3,
"column": 7
}
],
"path": [
"createGame"
],
"extensions": {
"code": "403",
"exception": {
"stacktrace": [
"Error: Error: Token has expired"
]
}
}
}
],
"data": {
"createGame": null
}
},
"status": 200,
"statusText": "OK",
"headers": {
"content-type": "application/json; charset=utf-8"
},
"config": {
"url": "http://localhost:4200/graphql",
"method": "post",
"data": "{\"query\":\"\\n mutation {\\n createGame (name: \\\"SA\\\", shortName: \\\"s\\\") {\\n id,\\n name,\\n shortName\\n }\\n }\\n \"}",
"headers": {
"Accept": "application/json, text/plain, */*",
"Content-Type": "application/json",
"authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjp7ImlkIjoxLCJlbXBsb3llZUlkIjowLCJ1c2VyUm9sZUlkIjozLCJwYXNzd29yZCI6IiQyYiQxMCRwNTE2V1hnSGZXdWx6czVmY2o2ZGp1Q09lUzF0UUw3U2MySEIuMDRPUmpWekh6VnduSTNwNiIsImlzQWN0aXZlIjp0cnVlLCJjcmVhdGVkQXQiOiIyMDE5LTA4LTE5VDA5OjMxOjA5LjAzOVoiLCJ1cGRhdGVkQXQiOiIyMDE5LTA4LTE5VDA5OjMxOjA5LjA0MVoifSwiaWF0IjoxNTY3ODcyNTk2LCJleHAiOjE1Njc4NzI2MDZ9.HpNE9m5YEUv0qgBHxsEoQMd1p29TkOqvQzYF7ptljJ0"
},
"baseURL": "http://localhost:4200/graphql",
"transformRequest": [
null
],
"transformResponse": [
null
],
"timeout": 0,
"xsrfCookieName": "XSRF-TOKEN",
"xsrfHeaderName": "X-XSRF-TOKEN",
"maxContentLength": -1
},
"request": {}
}
我遇到的问题是我在自己的前端中集成了axios响应拦截器
http.interceptors.response.use(
/**
* Leave response as it is.
*/
(response: any) => response,
/**
* This interceptor checks if the response had a 401 status code, which means
* that the access token used for the request has expired. It then refreshes
* the access token and resends the original request.
*/
unauthorizedResponseHandlerInterceptor
);
unauthorizedResponseHandlerInterceptor
函数仅在出现错误时由Axios调用,但是我的graphql服务器返回状态为200,因此该函数不会被调用。
我是否可以修改axios响应拦截器,以便它检查 data.errors 中的值,而不是 status
答案 0 :(得分:1)
没有错误时,将调用拦截器的第一个回调。您可以根据API发送错误的方式进行一些自定义检查:
http.interceptors.response.use(
/**
* Leave response as it is.
*/
(response: any) => {
if (response.data.errors) {
let customError = new Error(response.data.errors[0].message);
response.original_status = response.status
response.status = response.data.errors[0].extensions.code
customError.response = response;
return Promise.reject(customError);
}
return response;
},
/**
* This interceptor checks if the response had a 401 status code, which means
* that the access token used for the request has expired. It then refreshes
* the access token and resends the original request.
*/
unauthorizedResponseHandlerInterceptor
);
它非常灵活。如上所示,您甚至可以通过在拦截器中返回Promise.reject()
来将成功的调用转换为错误。
以下是玩弄的小提琴:https://jsfiddle.net/acdcjunior/pvb1kj87/
axios.interceptors.response.use((response) => {
if (response.data.errors) {
let customError = new Error(response.data.errors[0].message);
response.original_status = response.status
response.status = response.data.errors[0].extensions.code
// add some properties to make it look like a regular axios error
customError.response = response;
customError.request = response.request;
customError.config = response.config;
customError.isAxiosError = true; // or not
return Promise.reject(customError);
}
return response;
}, (error) => {
// Do something with response error
return Promise.reject(error);
});
(async () => {
console.log('*** regular axios error:')
await axios.get(`https://example.com/DOESNOTEXIST`)
.then((data) => {
console.log('success -->', data)
})
.catch((e) => {
console.log('error -->', e)
})
console.log('*\n*\n*')
console.log('*** simulating error:')
axios.get(`https://api.myjson.com/bins/d7hbp`)
.then((data) => {
console.log('success -->', data)
})
.catch((e) => {
console.log('error -->', e)
})
})();
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
Open dev tools and check the console!