问题描述
最近遇到问题,axios会在加密后的请求体加上双引号,导致后端解码失败。
问题排查
经过一番摸索,找到了axios处理body内容的逻辑:
// data即axios.data,请求体数据,headers为请求头信息
transformRequest: [function transformRequest(data, headers) {
const contentType = headers.getContentType() || '';
const hasJSONContentType = contentType.indexOf('application/json') > -1;
const isObjectPayload = utils.isObject(data);
if (isObjectPayload && utils.isHTMLForm(data)) {
data = new FormData(data);
}
const isFormData = utils.isFormData(data);
if (isFormData) {
return hasJSONContentType ? JSON.stringify(formDataToJSON(data)) : data;
}
if (utils.isArrayBuffer(data) ||
utils.isBuffer(data) ||
utils.isStream(data) ||
utils.isFile(data) ||
utils.isBlob(data) ||
utils.isReadableStream(data)
) {
return data;
}
if (utils.isArrayBufferView(data)) {
return data.buffer;
}
if (utils.isURLSearchParams(data)) {
headers.setContentType('application/x-www-form-urlencoded;charset=utf-8', false);
return data.toString();
}
let isFileList;
if (isObjectPayload) {
if (contentType.indexOf('application/x-www-form-urlencoded') > -1) {
return toURLEncodedForm(data, this.formSerializer).toString();
}
if ((isFileList = utils.isFileList(data)) || contentType.indexOf('multipart/form-data') > -1) {
const _FormData = this.env && this.env.FormData;
return toFormData(
isFileList ? {'files[]': data} : data,
_FormData && new _FormData(),
this.formSerializer
);
}
}
// 注意这里就是处理json数据的逻辑,只要请求头携带'application/json',或者data是个对象,就会对data进行JSON.stringfy操作
if (isObjectPayload || hasJSONContentType ) {
headers.setContentType('application/json', false);
return stringifySafely(data);
}
return data;
}
注意这段代码:
body内容的双引号就是这么来的
解决方案
知道了问题就很好解决了
-
可以考虑将请求头中的
content-type改成其他类型,就不再会被axios字符串化。但是这样需要调整后端逻辑,遂没有使用该方法 -
最终增加了axios的处理逻辑,必须满足body不是string,并且
content-type是application/json才进行字符串化
const request = axios.create({
transformRequest: function transformRequest(data: any, headers: any) {
const hasJSONContentType = () => {
const contentType = (headers && headers["Content-Type"]) || "";
return contentType.indexOf("application/json") > -1;
};
if (typeof data === "string" && hasJSONContentType()) {
return data;
}
return (axios.defaults.transformRequest as any)?.[0](data, headers);
}
});