Axios does not return XML error message from S3 when uploading asset over the size limit

Viewed 139

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
           }
       };
1 Answers

Axios cannot automatically parse XML. You can get the response as a string if you use the text response type.

config = {...config, responseType: 'text'}

Then, the response will be included in answer.data as a string. Of course, if you need to do anything smarter than just printing the response, you'll still need to parse it by using the DOMParser, for example.

Related