Vue JS,Axios 重试请求。防止 JSON 引号
Vue JS, Axios retry request. Prevent JSON quotes
我有一个 axios 拦截器,用于需要用户获得授权的情况,但他没有。例如,因为令牌已过期。
现在,令牌刷新后,应重试原始请求。
但是,目前原始请求似乎已更改,因此服务器给我一个 JSON.parse 错误。
SyntaxError: Unexpected token " in JSON at position 0
at JSON.parse (<anonymous>)
at createStrictSyntaxError (/var/app/current/node_modules/body-parser/lib/types/json.js:158:10)
at parse (/var/app/current/node_modules/body-parser/lib/types/json.js:83:15)
at /var/app/current/node_modules/body-parser/lib/read.js:121:18
at invokeCallback (/var/app/current/node_modules/raw-body/index.js:224:16)
at done (/var/app/current/node_modules/raw-body/index.js:213:7)
at IncomingMessage.onEnd (/var/app/current/node_modules/raw-body/index.js:273:7)
at IncomingMessage.emit (events.js:314:20)
at IncomingMessage.EventEmitter.emit (domain.js:483:12)
at endReadableNT (_stream_readable.js:1241:12)
这是因为,而不是原来的请求,即JSON,它似乎再次处理它,把它放在引号等中,所以它变成了一个字符串和bodyparser,抛出上面的错误.
所以请求内容,变成:
"{\"traderaccount\":\"{\\"traderaccountID\\":\\"undefined\\",\\"traderID\\":\\"2\\",\\"name\\":\\"Conscientious\\",\\"order\\":99,\\"myFxLink\\":\\"\\",\\"myFxWidget\\":\\"\\",\\"copyFxLink\\":\\"83809\\",\\"tokenLink\\":\\"\\",\\"tradertext\\":{\\"tradertextID\\":\\"\\",\\"traderaccountID\\":\\"\\",\\"language\\":\\"\\",\\"commission\\":\\"\\",\\"affiliateSystem\\":\\"\\",\\"leverage\\":\\"\\",\\"mode\\":\\"\\",\\"description\\":\\"\\"},\\"accountType\\":\\"\\",\\"accountTypeID\\":1,\\"minInvest\\":2000,\\"currency\\":\\"\\",\\"currencySymbol\\":\\"\\",\\"currencyID\\":1,\\"affiliateSystem\\":1}\"}"
而不是
{"traderaccount":"{\"traderaccountID\":\"undefined\",\"traderID\":\"2\",\"name\":\"Conscientious\",\"order\":99,\"myFxLink\":\"\",\"myFxWidget\":\"\",\"copyFxLink\":\"83809\",\"tokenLink\":\"\",\"tradertext\":{\"tradertextID\":\"\",\"traderaccountID\":\"\",\"language\":\"\",\"commission\":\"\",\"affiliateSystem\":\"\",\"leverage\":\"\",\"mode\":\"\",\"description\":\"\"},\"accountType\":\"\",\"accountTypeID\":1,\"minInvest\":2000,\"currency\":\"\",\"currencySymbol\":\"\",\"currencyID\":1,\"affiliateSystem\":1}"}
来自axios原请求内容。
都是未格式化的请求内容,我在开发者网络控制台可以看到。
两种情况下的内容类型都是 application/json。
下面是拦截器代码:
Axios.interceptors.response.use(
(response) => {
return response;
},
(err) => {
const error = err.response;
if (
error !== undefined &&
error.status === 401 &&
error.config &&
!error.config.__isRetryRequest
) {
if (this.$store.state.refreshToken === "") {
return Promise.reject(error);
}
return this.getAuthToken().then(() => {
const request = error.config;
request.headers.Authorization =
Axios.defaults.headers.common[globals.AXIOSAuthorization];
request.__isRetryRequest = true;
return Axios.request(request);
});
}
return Promise.reject(error);
}
);
private getAuthToken() {
if (!this.currentRequest) {
this.currentRequest = this.$store.dispatch("refreshToken");
this.currentRequest.then(
this.resetAuthTokenRequest,
this.resetAuthTokenRequest
);
}
return this.currentRequest;
}
private resetAuthTokenRequest() {
this.currentRequest = null;
}
// store refreshToken
async refreshToken({ commit }) {
const userID = this.state.userID;
const refreshToken = Vue.prototype.$cookies.get("refreshToken");
this.commit("refreshLicense");
commit("authRequest");
try {
const resp = await axios.post(serverURL + "/refreshToken", {
userID,
refreshToken,
});
if (resp.status === 200) {
return;
} else if (resp.status === 201) {
const token = resp.data.newToken;
const newRefreshToken = resp.data.newRefreshToken;
Vue.$cookies.set(
"token",
token,
"14d",
undefined,
undefined,
process.env.NODE_ENV === "production",
"Strict"
);
Vue.$cookies.set(
"refreshToken",
newRefreshToken,
"30d",
undefined,
undefined,
process.env.NODE_ENV === "production",
"Strict"
);
axios.defaults.headers.common[globals.AXIOSAuthorization] = token;
commit("authSuccessRefresh", { newRefreshToken });
} else {
this.dispatch("logout");
router.push({
name: "login",
});
}
} catch (e) {
commit("authError");
this.dispatch("logout");
}
那么,能不能帮我防止axios在重试的请求上更改请求内容。所以它不把它放在引号中并引用已经存在的引号?
感谢评论,我找到了解决方案。
在重新发送之前尝试解析内容:
axios.interceptors.response.use(
(response) => response,
(error) => {
const status = error.response ? error.response.status : null;
if (status === 401 && error.config && !error.config.__isRetryRequest) {
return refreshToken(useStore()).then(() => {
const request = error.config;
request.headers.Authorization =
axios.defaults.headers.common["Authorization"];
request.__isRetryRequest = true;
try {
const o = JSON.parse(request.data);
if (o && typeof o === "object") {
request.data = o;
}
} catch (e) {
return axios.request(request);
}
return axios.request(request);
});
}
return Promise.reject(error);
});
我有一个 axios 拦截器,用于需要用户获得授权的情况,但他没有。例如,因为令牌已过期。 现在,令牌刷新后,应重试原始请求。 但是,目前原始请求似乎已更改,因此服务器给我一个 JSON.parse 错误。
SyntaxError: Unexpected token " in JSON at position 0
at JSON.parse (<anonymous>)
at createStrictSyntaxError (/var/app/current/node_modules/body-parser/lib/types/json.js:158:10)
at parse (/var/app/current/node_modules/body-parser/lib/types/json.js:83:15)
at /var/app/current/node_modules/body-parser/lib/read.js:121:18
at invokeCallback (/var/app/current/node_modules/raw-body/index.js:224:16)
at done (/var/app/current/node_modules/raw-body/index.js:213:7)
at IncomingMessage.onEnd (/var/app/current/node_modules/raw-body/index.js:273:7)
at IncomingMessage.emit (events.js:314:20)
at IncomingMessage.EventEmitter.emit (domain.js:483:12)
at endReadableNT (_stream_readable.js:1241:12)
这是因为,而不是原来的请求,即JSON,它似乎再次处理它,把它放在引号等中,所以它变成了一个字符串和bodyparser,抛出上面的错误. 所以请求内容,变成:
"{\"traderaccount\":\"{\\"traderaccountID\\":\\"undefined\\",\\"traderID\\":\\"2\\",\\"name\\":\\"Conscientious\\",\\"order\\":99,\\"myFxLink\\":\\"\\",\\"myFxWidget\\":\\"\\",\\"copyFxLink\\":\\"83809\\",\\"tokenLink\\":\\"\\",\\"tradertext\\":{\\"tradertextID\\":\\"\\",\\"traderaccountID\\":\\"\\",\\"language\\":\\"\\",\\"commission\\":\\"\\",\\"affiliateSystem\\":\\"\\",\\"leverage\\":\\"\\",\\"mode\\":\\"\\",\\"description\\":\\"\\"},\\"accountType\\":\\"\\",\\"accountTypeID\\":1,\\"minInvest\\":2000,\\"currency\\":\\"\\",\\"currencySymbol\\":\\"\\",\\"currencyID\\":1,\\"affiliateSystem\\":1}\"}"
而不是
{"traderaccount":"{\"traderaccountID\":\"undefined\",\"traderID\":\"2\",\"name\":\"Conscientious\",\"order\":99,\"myFxLink\":\"\",\"myFxWidget\":\"\",\"copyFxLink\":\"83809\",\"tokenLink\":\"\",\"tradertext\":{\"tradertextID\":\"\",\"traderaccountID\":\"\",\"language\":\"\",\"commission\":\"\",\"affiliateSystem\":\"\",\"leverage\":\"\",\"mode\":\"\",\"description\":\"\"},\"accountType\":\"\",\"accountTypeID\":1,\"minInvest\":2000,\"currency\":\"\",\"currencySymbol\":\"\",\"currencyID\":1,\"affiliateSystem\":1}"}
来自axios原请求内容。 都是未格式化的请求内容,我在开发者网络控制台可以看到。
两种情况下的内容类型都是 application/json。
下面是拦截器代码:
Axios.interceptors.response.use(
(response) => {
return response;
},
(err) => {
const error = err.response;
if (
error !== undefined &&
error.status === 401 &&
error.config &&
!error.config.__isRetryRequest
) {
if (this.$store.state.refreshToken === "") {
return Promise.reject(error);
}
return this.getAuthToken().then(() => {
const request = error.config;
request.headers.Authorization =
Axios.defaults.headers.common[globals.AXIOSAuthorization];
request.__isRetryRequest = true;
return Axios.request(request);
});
}
return Promise.reject(error);
}
);
private getAuthToken() {
if (!this.currentRequest) {
this.currentRequest = this.$store.dispatch("refreshToken");
this.currentRequest.then(
this.resetAuthTokenRequest,
this.resetAuthTokenRequest
);
}
return this.currentRequest;
}
private resetAuthTokenRequest() {
this.currentRequest = null;
}
// store refreshToken
async refreshToken({ commit }) {
const userID = this.state.userID;
const refreshToken = Vue.prototype.$cookies.get("refreshToken");
this.commit("refreshLicense");
commit("authRequest");
try {
const resp = await axios.post(serverURL + "/refreshToken", {
userID,
refreshToken,
});
if (resp.status === 200) {
return;
} else if (resp.status === 201) {
const token = resp.data.newToken;
const newRefreshToken = resp.data.newRefreshToken;
Vue.$cookies.set(
"token",
token,
"14d",
undefined,
undefined,
process.env.NODE_ENV === "production",
"Strict"
);
Vue.$cookies.set(
"refreshToken",
newRefreshToken,
"30d",
undefined,
undefined,
process.env.NODE_ENV === "production",
"Strict"
);
axios.defaults.headers.common[globals.AXIOSAuthorization] = token;
commit("authSuccessRefresh", { newRefreshToken });
} else {
this.dispatch("logout");
router.push({
name: "login",
});
}
} catch (e) {
commit("authError");
this.dispatch("logout");
}
那么,能不能帮我防止axios在重试的请求上更改请求内容。所以它不把它放在引号中并引用已经存在的引号?
感谢评论,我找到了解决方案。 在重新发送之前尝试解析内容:
axios.interceptors.response.use(
(response) => response,
(error) => {
const status = error.response ? error.response.status : null;
if (status === 401 && error.config && !error.config.__isRetryRequest) {
return refreshToken(useStore()).then(() => {
const request = error.config;
request.headers.Authorization =
axios.defaults.headers.common["Authorization"];
request.__isRetryRequest = true;
try {
const o = JSON.parse(request.data);
if (o && typeof o === "object") {
request.data = o;
}
} catch (e) {
return axios.request(request);
}
return axios.request(request);
});
}
return Promise.reject(error);
});