Axios does not return XML error message from S3 when uploading asset over the size limit.
Environment
- Axios Version : 0.24.0
- Node.js Version: v14.17.4
- OS: Mac OS 12.3
S3 is returning this XML error message when I try to uplaod an asset over teh size limit
UPLOAD FAILED. Status Code: 400. Error message:
<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Error><Code>EntityTooLarge</Code><Message>Your proposed upload exceeds the maximum allowed size</Message><ProposedSize>52432788</ProposedSize><MaxSizeAllowed>52428800</MaxSizeAllowed><RequestId>N8RFYCS0K10GB4FF</RequestId><HostId>2OaG69rf19DMxItXx8J//rscZuSbxU8hJ/93du/a1zaFwAZa6jN2v1xCDebW4MRMgW3Kfuw0n10=</HostId></Error>
But Axios:
- does not return it, just returns a generic error message:
Request failed with status code 400" - and also breaks when trying to parse it.
This is the code I am running for the upload to S3:
let dataForm = new FormData();
dataForm.append('key', functionParams.uploadData.fields.key);
dataForm.append('bucket', functionParams.uploadData.fields.bucket);
dataForm.append('X-Amz-Algorithm', functionParams.uploadData.fields['X-Amz-Algorithm']);
dataForm.append('X-Amz-Credential', functionParams.uploadData.fields['X-Amz-Credential']);
dataForm.append('X-Amz-Date', functionParams.uploadData.fields['X-Amz-Date']);
dataForm.append('Policy', functionParams.uploadData.fields.Policy);
dataForm.append('X-Amz-Signature', functionParams.uploadData.fields['X-Amz-Signature']);
dataForm.append('file', fs.createReadStream(functionParams.assetFullPath),
{ knownLength: fs.statSync(functionParams.assetFullPath).size }
);
const uploadServiceURL = uploadData.url;
var config = {
method: 'POST',
url: uploadServiceURL,
headers: {
...dataForm.getHeaders(),
'content-length': dataForm.getLengthSync()
},
data: dataForm,
maxContentLength: Infinity,
maxBodyLength: Infinity,
transitional: {
forcedJSONParsing: false,
silentJSONParsing: false,
clarifyTimeoutError: true
}
};
axios(config)
.then(answer => {
resolve(answer);
})
.catch((error) => {
console.log(`Error:`)
console.log(error.toJSON())
reject(error)
})
This is the error I get from Axios:
{
"message": "Request failed with status code 400",
"name": "Error",
"stack": "Error: Request failed with status code 400\n at createError (/Users/vlad/modules/node_modules/axios/lib/core/createError.js:16:15)\n at settle (/Users/vlad/modules/axios/lib/core/settle.js:17:12)\n at IncomingMessage.handleStreamEnd (/Users/vlad/modules/node_modules/axios/lib/adapters/http.js:322:11)\n at IncomingMessage.emit (events.js:412:35)\n at endReadableNT (internal/streams/readable.js:1317:12)\n at processTicksAndRejections (internal/process/task_queues.js:82:21)",
"config": {
"transitional": {
"silentJSONParsing": false,
"forcedJSONParsing": false,
"clarifyTimeoutError": true
},
"transformRequest": [
null
],
"transformResponse": [
null
],
"timeout": 0,
"xsrfCookieName": "XSRF-TOKEN",
"xsrfHeaderName": "X-XSRF-TOKEN",
"maxContentLength": null,
"maxBodyLength": null,
"headers": {
"Accept": "application/json, text/plain, */*",
"Content-Type": "multipart/form-data; boundary=--------------------------913873697821807580301477",
"content-length": 114310407,
"User-Agent": "axios/0.26.0"
},
"method": "post",
"url": "https://s3.us-east-1.amazonaws.com/public-assets.bluescape.com",
"data": {
"_overheadLength": 938,
"_valueLength": 114309413,
"_valuesToMeasure": [],
"writable": false,
"readable": true,
"dataSize": 0,
"maxDataSize": 2097152,
"pauseStreams": true,
"_released": true,
"_streams": [],
"_currentStream": null,
"_insideLoop": false,
"_pendingNext": false,
"_boundary": "--------------------------913873697821807580301477",
"_events": {},
"_eventsCount": 1
},
"axios-retry": {
"retryCount": 0,
"lastRequestTime": 1648080399442
}
},
"status": 400
}
Any idea how can I get back the XML from S3 describing the issue? I want to present it as the cause of the error.
I have tried using “transformResponse“ to transform the response from remote server, but I cannot make it work and accept a new error message:
var config = {
method: 'POST',
url: uploadServiceURL,
headers: {
...dataForm.getHeaders(),
'content-length': dataForm.getLengthSync()
},
data: dataForm,
maxContentLength: Infinity,
maxBodyLength: Infinity,
transformResponse: [(response, headers) => {
var resp = response;
// Note: A successful upload to S3 will return an empty response, status code 204
if (response) {
console.log(` ---> response for ${functionParams.assetFullPath} : ${JSON.stringify(response, null, ' ')} `)
var resp;
try {
// Detect an error when parsing the answer: XML or something else
resp = JSON.parse(response)
console.log(`==> answer parsed:`)
console.log(JSON.stringify(resp, null, ' '))
} catch (error) {
console.log(` ===> ERROR parsing response for ${functionParams.assetFullPath}: ${JSON.stringify(error, null, ' ')}`)
// Trying to construct an XML response
resp = {
"test message": "manually created error message"
}
}
}
console.log(`----> Response to send back: ${JSON.stringify(resp, null, ' ')}`)
return resp;
}, ...axios.defaults.transformRequest],
transitional: {
forcedJSONParsing: false,
silentJSONParsing: false,
clarifyTimeoutError: true
}
};