@gideo-llc/backblaze-b2-upload-any
Version:
An intelligent upload function to be used with the backblaze-b2 module
85 lines (72 loc) • 2.71 kB
JavaScript
// In our tests, B2 frequently hangs up and doesn't send or receive data.
// Unfortunately, axios does not give us a good way to detect this or react to
// it, so for some calls we will directly use node's http client with a socket
// timeout set.
const https = require('https');
module.exports = (url, options, body) => {
return new Promise((resolve, reject) => {
let axiosResponse;
const request = https.request(url, options, response => {
axiosResponse = {
status: response.statusCode,
headers: response.headers,
};
response.setEncoding('utf8');
let buf = '';
response.on('error', fail);
response.on('data', chunk => { buf += chunk; });
response.on('end', () => {
const success = response.statusCode >= 200 && response.statusCode < 400;
let data;
try {
data = JSON.parse(buf);
} catch (err) {
if (success) {
// If the request was otherwise successful but we can't
// parse the body, fail with the JSON parse error.
fail(err);
}
}
if (success) {
resolve(data);
} else {
axiosResponse.data = data;
fail(new Error(`Request failed with status code ${response.statusCode}`));
}
});
});
function fail(err) {
// On failure we need to simulate enough of the axios error
// structure for our borrow() function to know what to do.
reject(Object.assign(err, {
config: {
url,
method: options.method,
},
response: axiosResponse,
}));
request.aborted || request.abort();
}
request.on('error', fail);
request.on('timeout', () => {
fail(
Object.assign(
new Error('Request timed out'),
{ code: 'ETIMEDOUT' }
)
);
});
if (body) {
if (typeof body === 'string') {
request.write(body, 'utf8');
} else if (Buffer.isBuffer(body)) {
request.write(body);
} else if (typeof body.read === 'function') {
body.on('error', fail)
.pipe(request);
return; // skip ending the request
}
}
request.end();
});
};