mirror of
https://github.com/tenrok/axios.git
synced 2026-06-17 19:21:29 +03:00
bd3816bf9e
* fix(dispatchRequest): attach response to AxiosError on JSON parse failure When JSON.parse fails in strict mode (responseType: 'json' or silentJSONParsing: false), the thrown AxiosError was missing both error.response and error.status because transformResponse has no direct access to the response object — only the config is available as `this` inside transformData. Root cause: transformData is called as transformData.call(config, ...) and AxiosError.from uses `this.response` to populate the error's response field, but config.response was never set. Fix: in dispatchRequest, temporarily assign the response object to config.response before invoking transformData, then clean it up in a finally block to avoid permanently polluting the config object. This ensures error.response and error.status are available when a request with responseType='json' receives a malformed JSON body, making the error consistent with all other AxiosError instances. Fixes #7224 * chore: added additional testing and removed the misleading test --------- Co-authored-by: AKIBUZZAMAN AKIB <akibuzzamanakib473@gmail.com> Co-authored-by: Jason Saayman <jasonsaayman@gmail.com>
90 lines
2.6 KiB
JavaScript
90 lines
2.6 KiB
JavaScript
'use strict';
|
|
|
|
import transformData from './transformData.js';
|
|
import isCancel from '../cancel/isCancel.js';
|
|
import defaults from '../defaults/index.js';
|
|
import CanceledError from '../cancel/CanceledError.js';
|
|
import AxiosHeaders from '../core/AxiosHeaders.js';
|
|
import adapters from '../adapters/adapters.js';
|
|
|
|
/**
|
|
* Throws a `CanceledError` if cancellation has been requested.
|
|
*
|
|
* @param {Object} config The config that is to be used for the request
|
|
*
|
|
* @returns {void}
|
|
*/
|
|
function throwIfCancellationRequested(config) {
|
|
if (config.cancelToken) {
|
|
config.cancelToken.throwIfRequested();
|
|
}
|
|
|
|
if (config.signal && config.signal.aborted) {
|
|
throw new CanceledError(null, config);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Dispatch a request to the server using the configured adapter.
|
|
*
|
|
* @param {object} config The config that is to be used for the request
|
|
*
|
|
* @returns {Promise} The Promise to be fulfilled
|
|
*/
|
|
export default function dispatchRequest(config) {
|
|
throwIfCancellationRequested(config);
|
|
|
|
config.headers = AxiosHeaders.from(config.headers);
|
|
|
|
// Transform request data
|
|
config.data = transformData.call(config, config.transformRequest);
|
|
|
|
if (['post', 'put', 'patch'].indexOf(config.method) !== -1) {
|
|
config.headers.setContentType('application/x-www-form-urlencoded', false);
|
|
}
|
|
|
|
const adapter = adapters.getAdapter(config.adapter || defaults.adapter, config);
|
|
|
|
return adapter(config).then(
|
|
function onAdapterResolution(response) {
|
|
throwIfCancellationRequested(config);
|
|
|
|
// Expose the current response on config so that transformResponse can
|
|
// attach it to any AxiosError it throws (e.g. on JSON parse failure).
|
|
// We clean it up afterwards to avoid polluting the config object.
|
|
config.response = response;
|
|
try {
|
|
response.data = transformData.call(config, config.transformResponse, response);
|
|
} finally {
|
|
delete config.response;
|
|
}
|
|
|
|
response.headers = AxiosHeaders.from(response.headers);
|
|
|
|
return response;
|
|
},
|
|
function onAdapterRejection(reason) {
|
|
if (!isCancel(reason)) {
|
|
throwIfCancellationRequested(config);
|
|
|
|
// Transform response data
|
|
if (reason && reason.response) {
|
|
config.response = reason.response;
|
|
try {
|
|
reason.response.data = transformData.call(
|
|
config,
|
|
config.transformResponse,
|
|
reason.response
|
|
);
|
|
} finally {
|
|
delete config.response;
|
|
}
|
|
reason.response.headers = AxiosHeaders.from(reason.response.headers);
|
|
}
|
|
}
|
|
|
|
return Promise.reject(reason);
|
|
}
|
|
);
|
|
}
|