Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add onXHRProgress option #1107

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 47 additions & 27 deletions lib/browser/client.js
Original file line number Diff line number Diff line change
@@ -43,7 +43,7 @@ function Client(options, ctx) {
this.options = Client.initOptions(options);
}

this.options.cancelFlag = false;// cancel flag: if true need to be cancelled, default false
this.options.cancelFlag = false; // cancel flag: if true need to be cancelled, default false

// support custom agent and urllib client
if (this.options.urllib) {
@@ -68,18 +68,22 @@ module.exports = Client;

Client.initOptions = function initOptions(options) {
if (!options.stsToken) {
console.warn('Please use STS Token for safety, see more details at https://help.aliyun.com/document_detail/32077.html');
console.warn(
'Please use STS Token for safety, see more details at https://help.aliyun.com/document_detail/32077.html'
);
}
const opts = Object.assign({
secure: isHttpsWebProtocol(),
// for browser compatibility disable fetch.
useFetch: false,
}, options);
const opts = Object.assign(
{
secure: isHttpsWebProtocol(),
// for browser compatibility disable fetch.
useFetch: false
},
options
);

return _initOptions(opts);
};


/**
* prototype
*/
@@ -179,7 +183,12 @@ proto.authorization = function authorization(method, resource, subres, headers)
parameters: subres
});

return signUtils.authorization(this.options.accessKeyId, this.options.accessKeySecret, stringToSign, this.options.headerEncoding);
return signUtils.authorization(
this.options.accessKeyId,
this.options.accessKeySecret,
stringToSign,
this.options.headerEncoding
);
};

/**
@@ -204,8 +213,8 @@ proto.authorization = function authorization(method, resource, subres, headers)
proto.request = async function (params) {
if (this.options.retryMax) {
return await retry(request.bind(this), this.options.retryMax, {
errorHandler: (err) => {
const _errHandle = (_err) => {
errorHandler: err => {
const _errHandle = _err => {
if (params.stream) return false;
const statusErr = [-1, -2].includes(_err.status);
const requestErrorRetryHandle = this.options.requestErrorRetryHandle || (() => true);
@@ -233,7 +242,14 @@ async function request(params) {
const useStream = !!params.stream;
try {
result = await this.urllib.request(reqParams.url, reqParams.params);
this.debug('response %s %s, got %s, headers: %j', params.method, reqParams.url, result.status, result.headers, 'info');
this.debug(
'response %s %s, got %s, headers: %j',
params.method,
reqParams.url,
result.status,
result.headers,
'info'
);
} catch (err) {
reqErr = err;
}
@@ -282,7 +298,7 @@ proto._escape = function _escape(name) {
*/

proto._getUserAgent = function _getUserAgent() {
const agent = (process && process.browser) ? 'js' : 'nodejs';
const agent = process && process.browser ? 'js' : 'nodejs';
const sdk = `aliyun-sdk-${agent}/${pkg.version}`;
let plat = platform.description;
if (!plat && process) {
@@ -306,7 +322,7 @@ proto._checkUserAgent = function _checkUserAgent(ua) {
*/

proto.checkBrowserAndVersion = function checkBrowserAndVersion(name, version) {
return ((bowser.name === name) && (bowser.version.split('.')[0] === version));
return bowser.name === name && bowser.version.split('.')[0] === version;
};

/**
@@ -321,16 +337,20 @@ proto.parseXML = function parseXMLThunk(str) {
if (Buffer.isBuffer(str)) {
str = str.toString();
}
xml.parseString(str, {
explicitRoot: false,
explicitArray: false
}, (err, result) => {
if (err) {
reject(err);
} else {
resolve(result);
xml.parseString(
str,
{
explicitRoot: false,
explicitArray: false
},
(err, result) => {
if (err) {
reject(err);
} else {
resolve(result);
}
}
});
);
});
};

@@ -344,7 +364,8 @@ proto.parseXML = function parseXMLThunk(str) {
proto.requestError = async function requestError(result) {
let err = null;
if (!result.data || !result.data.length) {
if (result.status === -1 || result.status === -2) { // -1 is net error , -2 is timeout
if (result.status === -1 || result.status === -2) {
// -1 is net error , -2 is timeout
err = new Error(result.message);
err.name = result.name;
err.status = result.status;
@@ -375,7 +396,7 @@ proto.requestError = async function requestError(result) {

let info;
try {
info = await this.parseXML(message) || {};
info = (await this.parseXML(message)) || {};
} catch (error) {
this.debug(message, 'error');
error.message += `\nraw xml: ${message}`;
@@ -384,7 +405,7 @@ proto.requestError = async function requestError(result) {
return error;
}

let msg = info.Message || (`unknow request error, status: ${result.status}`);
let msg = info.Message || `unknow request error, status: ${result.status}`;
if (info.Condition) {
msg += ` (condition: ${info.Condition})`;
}
@@ -400,4 +421,3 @@ proto.requestError = async function requestError(result) {
this.debug('generate error %j', err, 'error');
return err;
};

45 changes: 32 additions & 13 deletions lib/browser/managed-upload.js
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@ const { isFile } = require('../common/utils/isFile');
const { isArray } = require('../common/utils/isArray');
const { isBuffer } = require('../common/utils/isBuffer');
const { retry } = require('../common/utils/retry');
const { calculatePercentage } = require('../common/utils/calculatePercentage');

const proto = exports;

@@ -119,6 +120,9 @@ proto._resumeMultipart = async function _resumeMultipart(checkpoint, options) {
}
const { file, fileSize, partSize, uploadId, doneParts, name } = checkpoint;

// total loaded percentage
const partDetail = {};

const internalDoneParts = [];

if (doneParts.length > 0) {
@@ -142,10 +146,24 @@ proto._resumeMultipart = async function _resumeMultipart(checkpoint, options) {
};

let result;
let onXHRProgress;
if (options.onXHRProgress) {
onXHRProgress = (p, l, t) => {
partDetail[partNo] = {
percentage: p,
loaded: l,
total: t
};
const detail = calculatePercentage(fileSize, partDetail);
options.onXHRProgress(detail.percentage, detail.loaded, detail.total);
};
}

try {
result = await self._uploadPart(name, uploadId, partNo, data, {
timeout: options.timeout,
disabledMD5: options.disabledMD5
disabledMD5: options.disabledMD5,
onXHRProgress
});
} catch (error) {
if (error.status === 404) {
@@ -195,18 +213,19 @@ proto._resumeMultipart = async function _resumeMultipart(checkpoint, options) {
const jobErr = await this._parallel(
todo,
parallel,
value => new Promise((resolve, reject) => {
uploadPartJob(that, value)
.then(result => {
if (result) {
internalDoneParts.push(result);
}
resolve();
})
.catch(err => {
reject(err);
});
})
value =>
new Promise((resolve, reject) => {
uploadPartJob(that, value)
.then(result => {
if (result) {
internalDoneParts.push(result);
}
resolve();
})
.catch(err => {
reject(err);
});
})
);
multipartFinish = true;

5 changes: 5 additions & 0 deletions lib/browser/object.js
Original file line number Diff line number Diff line change
@@ -88,6 +88,11 @@ proto.put = async function put(name, file, options) {
params.disabledMD5 = options.disabledMD5;
params.content = content;
params.successStatuses = [200];
if (options.onXHRProgress && typeof options.onXHRProgress === 'function') {
params.onXHRProgress = (percentage, loaded, total) => {
options.onXHRProgress(percentage, loaded, total);
};
}

const result = await this.request(params);

5 changes: 5 additions & 0 deletions lib/common/multipart.js
Original file line number Diff line number Diff line change
@@ -245,6 +245,11 @@ proto._uploadPart = async function _uploadPart(name, uploadId, partNo, data, opt
isBrowserEnv ? (params.content = data.content) : (params.stream = data.stream);
params.successStatuses = [200];
params.disabledMD5 = options.disabledMD5;
if (options.onXHRProgress && typeof options.onXHRProgress === 'function') {
params.onXHRProgress = (percentage, loaded, total) => {
options.onXHRProgress(percentage, loaded, total);
};
}

const result = await this.request(params);

5 changes: 5 additions & 0 deletions lib/common/utils/calculatePercentage.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export declare const calculatePercentage: (fileSize: number, partList: any) => {
percentage: number;
loaded: number;
total: number;
};
11 changes: 11 additions & 0 deletions lib/common/utils/calculatePercentage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.calculatePercentage = void 0;
exports.calculatePercentage = (fileSize, partList) => {
const result = { percentage: 0, loaded: 0, total: fileSize };
Object.keys(partList).forEach(i => {
result.loaded += partList[i].loaded;
});
result.percentage = (result.loaded / fileSize) * 100;
return result;
};
8 changes: 8 additions & 0 deletions lib/common/utils/calculatePercentage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export const calculatePercentage = (fileSize: number, partList: any) => {
const result = { percentage: 0, loaded: 0, total: fileSize };
Object.keys(partList).forEach(i => {
result.loaded += partList[i].loaded;
});
result.percentage = (result.loaded / fileSize) * 100;
return result;
};
10 changes: 4 additions & 6 deletions lib/common/utils/createRequest.js
Original file line number Diff line number Diff line change
@@ -24,7 +24,7 @@ function createRequest(params) {
date = +new Date() + this.options.amendTimeSkewed;
}
const headers = {
'x-oss-date': dateFormat(date, 'UTC:ddd, dd mmm yyyy HH:MM:ss \'GMT\''),
'x-oss-date': dateFormat(date, "UTC:ddd, dd mmm yyyy HH:MM:ss 'GMT'")
};
if (typeof window !== 'undefined') {
headers['x-oss-user-agent'] = this.userAgent;
@@ -52,10 +52,7 @@ function createRequest(params) {
}
if (params.content) {
if (!params.disabledMD5) {
headers['Content-MD5'] = crypto
.createHash('md5')
.update(Buffer.from(params.content, 'utf8'))
.digest('base64');
headers['Content-MD5'] = crypto.createHash('md5').update(Buffer.from(params.content, 'utf8')).digest('base64');
}
if (!headers['Content-Length']) {
headers['Content-Length'] = params.content.length;
@@ -86,7 +83,8 @@ function createRequest(params) {
timeout,
writeStream: params.writeStream,
customResponse: params.customResponse,
ctx: params.ctx || this.ctx
ctx: params.ctx || this.ctx,
onXHRProgress: params.onXHRProgress
};
if (this.agent) {
reqParams.agent = this.agent;
26 changes: 15 additions & 11 deletions lib/common/utils/createRequest.ts
Original file line number Diff line number Diff line change
@@ -10,13 +10,13 @@ const { setRegion } = require('./setRegion');
const { getReqUrl } = require('../client/getReqUrl');

interface Headers {
[propName: string]: any
'x-oss-date': string,
'x-oss-user-agent'?: string,
[propName: string]: any;
'x-oss-date': string;
'x-oss-user-agent'?: string;
}

interface ReqParams {
[propName: string]: any
[propName: string]: any;
}

function getHeader(headers: Headers, name: string) {
@@ -34,7 +34,7 @@ export function createRequest(this: any, params) {
date = +new Date() + this.options.amendTimeSkewed;
}
const headers: Headers = {
'x-oss-date': dateFormat(date, 'UTC:ddd, dd mmm yyyy HH:MM:ss \'GMT\''),
'x-oss-date': dateFormat(date, "UTC:ddd, dd mmm yyyy HH:MM:ss 'GMT'")
};

if (typeof window !== 'undefined') {
@@ -69,10 +69,7 @@ export function createRequest(this: any, params) {

if (params.content) {
if (!params.disabledMD5) {
headers['Content-MD5'] = crypto
.createHash('md5')
.update(Buffer.from(params.content, 'utf8'))
.digest('base64');
headers['Content-MD5'] = crypto.createHash('md5').update(Buffer.from(params.content, 'utf8')).digest('base64');
}
if (!headers['Content-Length']) {
headers['Content-Length'] = params.content.length;
@@ -87,7 +84,13 @@ export function createRequest(this: any, params) {
}

const authResource = this._getResource(params);
headers.authorization = this.authorization(params.method, authResource, params.subres, headers, this.options.headerEncoding);
headers.authorization = this.authorization(
params.method,
authResource,
params.subres,
headers,
this.options.headerEncoding
);

// const url = this._getReqUrl(params);
if (isIP(this.options.endpoint.hostname)) {
@@ -106,7 +109,8 @@ export function createRequest(this: any, params) {
timeout,
writeStream: params.writeStream,
customResponse: params.customResponse,
ctx: params.ctx || this.ctx
ctx: params.ctx || this.ctx,
onXHRProgress: params.onXHRProgress
};
if (this.agent) {
reqParams.agent = this.agent;
134 changes: 65 additions & 69 deletions shims/stream-http/index.js
Original file line number Diff line number Diff line change
@@ -1,86 +1,82 @@
//"version": "2.8.2",
var ClientRequest = require('./lib/request')
var response = require('./lib/response')
var extend = require('xtend')
var statusCodes = require('builtin-status-codes')
var url = require('url')
var ClientRequest = require('./lib/request');
var response = require('./lib/response');
var extend = require('xtend');
var statusCodes = require('builtin-status-codes');
var url = require('url');

var http = exports
var http = exports;

http.request = function (opts, cb) {
if (typeof opts === 'string')
opts = url.parse(opts)
else
opts = extend(opts)
if (typeof opts === 'string') opts = url.parse(opts);
else opts = extend(opts);

// Normally, the page is loaded from http or https, so not specifying a protocol
// will result in a (valid) protocol-relative url. However, this won't work if
// the protocol is something else, like 'file:'
var defaultProtocol = global.location.protocol.search(/^https?:$/) === -1 ? 'http:' : ''
// Normally, the page is loaded from http or https, so not specifying a protocol
// will result in a (valid) protocol-relative url. However, this won't work if
// the protocol is something else, like 'file:'
var defaultProtocol = global.location.protocol.search(/^https?:$/) === -1 ? 'http:' : '';

var protocol = opts.protocol || defaultProtocol
var host = opts.hostname || opts.host
var port = opts.port
var path = opts.path || '/'
var protocol = opts.protocol || defaultProtocol;
var host = opts.hostname || opts.host;
var port = opts.port;
var path = opts.path || '/';

// Necessary for IPv6 addresses
if (host && host.indexOf(':') !== -1)
host = '[' + host + ']'
// Necessary for IPv6 addresses
if (host && host.indexOf(':') !== -1) host = '[' + host + ']';

// This may be a relative url. The browser should always be able to interpret it correctly.
opts.url = (host ? (protocol + '//' + host) : '') + (port ? ':' + port : '') + path
opts.method = (opts.method || 'GET').toUpperCase()
opts.headers = opts.headers || {}
// This may be a relative url. The browser should always be able to interpret it correctly.
opts.url = (host ? protocol + '//' + host : '') + (port ? ':' + port : '') + path;
opts.method = (opts.method || 'GET').toUpperCase();
opts.headers = opts.headers || {};

// Also valid opts.auth, opts.mode
// Also valid opts.auth, opts.mode

var req = new ClientRequest(opts)
if (cb)
req.on('response', cb)
return req
}
var req = new ClientRequest(opts);
if (cb) req.on('response', cb);
return req;
};

http.get = function get (opts, cb) {
var req = http.request(opts, cb)
req.end()
return req
}
http.get = function get(opts, cb) {
var req = http.request(opts, cb);
req.end();
return req;
};

http.ClientRequest = ClientRequest
http.IncomingMessage = response.IncomingMessage
http.ClientRequest = ClientRequest;
http.IncomingMessage = response.IncomingMessage;

http.Agent = function () {}
http.Agent.defaultMaxSockets = 4
http.Agent = function () {};
http.Agent.defaultMaxSockets = 4;

http.globalAgent = new http.Agent()
http.globalAgent = new http.Agent();

http.STATUS_CODES = statusCodes
http.STATUS_CODES = statusCodes;

http.METHODS = [
'CHECKOUT',
'CONNECT',
'COPY',
'DELETE',
'GET',
'HEAD',
'LOCK',
'M-SEARCH',
'MERGE',
'MKACTIVITY',
'MKCOL',
'MOVE',
'NOTIFY',
'OPTIONS',
'PATCH',
'POST',
'PROPFIND',
'PROPPATCH',
'PURGE',
'PUT',
'REPORT',
'SEARCH',
'SUBSCRIBE',
'TRACE',
'UNLOCK',
'UNSUBSCRIBE'
]
'CHECKOUT',
'CONNECT',
'COPY',
'DELETE',
'GET',
'HEAD',
'LOCK',
'M-SEARCH',
'MERGE',
'MKACTIVITY',
'MKCOL',
'MOVE',
'NOTIFY',
'OPTIONS',
'PATCH',
'POST',
'PROPFIND',
'PROPPATCH',
'PURGE',
'PUT',
'REPORT',
'SEARCH',
'SUBSCRIBE',
'TRACE',
'UNLOCK',
'UNSUBSCRIBE'
];
579 changes: 290 additions & 289 deletions shims/stream-http/lib/request.js

Large diffs are not rendered by default.

111 changes: 67 additions & 44 deletions shims/xhr.js
Original file line number Diff line number Diff line change
@@ -38,10 +38,7 @@ function makeCallback(resolve, reject) {
// exports.TIMEOUT = ms('5s');
exports.TIMEOUTS = [ms('300s'), ms('300s')];

const TEXT_DATA_TYPES = [
'json',
'text'
];
const TEXT_DATA_TYPES = ['json', 'text'];

exports.request = function request(url, args, callback) {
// request(url, callback)
@@ -58,11 +55,9 @@ exports.request = function request(url, args, callback) {
});
};


exports.requestWithCallback = function requestWithCallback(url, args, callback) {
if (!url || (typeof url !== 'string' && typeof url !== 'object')) {
const msg = util.format('expect request url to be a string or a http request options, but got' +
' %j', url);
const msg = util.format('expect request url to be a string or a http request options, but got' + ' %j', url);
throw new Error(msg);
}

@@ -83,7 +78,7 @@ exports.requestWithCallback = function requestWithCallback(url, args, callback)
requestId: reqId,
url: url,
args: args,
ctx: args.ctx,
ctx: args.ctx
};
if (args.emitter) {
args.emitter.emit('request', reqMeta);
@@ -133,11 +128,12 @@ exports.requestWithCallback = function requestWithCallback(url, args, callback)
port: port,
agent: agent,
headers: args.headers || {},
onXHRProgress: args.onXHRProgress,
// default is dns.lookup
// https://github.com/nodejs/node/blob/master/lib/net.js#L986
// custom dnslookup require node >= 4.0.0
// https://github.com/nodejs/node/blob/archived-io.js-v0.12/lib/net.js#L952
lookup: args.lookup,
lookup: args.lookup
};

if (Array.isArray(args.timeout)) {
@@ -250,7 +246,7 @@ exports.requestWithCallback = function requestWithCallback(url, args, callback)
requestSent: 0,
// Time to first byte (TTFB)
waiting: 0,
contentDownload: 0,
contentDownload: 0
};
}

@@ -270,12 +266,25 @@ exports.requestWithCallback = function requestWithCallback(url, args, callback)
function done(err, data, res) {
cancelResponseTimer();
if (!callback) {
console.warn('[urllib:warn] [%s] [%s] [worker:%s] %s %s callback twice!!!',
Date(), reqId, process.pid, options.method, url);
console.warn(
'[urllib:warn] [%s] [%s] [worker:%s] %s %s callback twice!!!',
Date(),
reqId,
process.pid,
options.method,
url
);
// https://github.com/node-modules/urllib/pull/30
if (err) {
console.warn('[urllib:warn] [%s] [%s] [worker:%s] %s: %s\nstack: %s',
Date(), reqId, process.pid, err.name, err.message, err.stack);
console.warn(
'[urllib:warn] [%s] [%s] [worker:%s] %s: %s\nstack: %s',
Date(),
reqId,
process.pid,
err.name,
err.message,
err.stack
);
}
return;
}
@@ -308,9 +317,17 @@ exports.requestWithCallback = function requestWithCallback(url, args, callback)
timing.contentDownload = requestUseTime;
}

debug('[%sms] done, %s bytes HTTP %s %s %s %s, keepAliveSocket: %s, timing: %j',
requestUseTime, responseSize, statusCode, options.method, options.host, options.path,
keepAliveSocket, timing);
debug(
'[%sms] done, %s bytes HTTP %s %s %s %s, keepAliveSocket: %s, timing: %j',
requestUseTime,
responseSize,
statusCode,
options.method,
options.host,
options.path,
keepAliveSocket,
timing
);

const response = {
status: statusCode,
@@ -324,7 +341,7 @@ exports.requestWithCallback = function requestWithCallback(url, args, callback)
requestUrls: args.requestUrls,
timing: timing,
remoteAddress: remoteAddress,
remotePort: remotePort,
remotePort: remotePort
};

if (err) {
@@ -333,9 +350,21 @@ exports.requestWithCallback = function requestWithCallback(url, args, callback)
// add current agent status to error message for logging and debug
agentStatus = ', agent status: ' + JSON.stringify(agent.getCurrentStatus());
}
err.message += ', ' + options.method + ' ' + url + ' ' + statusCode
+ ' (connected: ' + connected + ', keepalive socket: ' + keepAliveSocket + agentStatus + ')'
+ '\nheaders: ' + JSON.stringify(headers);
err.message +=
', ' +
options.method +
' ' +
url +
' ' +
statusCode +
' (connected: ' +
connected +
', keepalive socket: ' +
keepAliveSocket +
agentStatus +
')' +
'\nheaders: ' +
JSON.stringify(headers);
err.data = data;
err.path = options.path;
err.status = statusCode;
@@ -357,14 +386,15 @@ exports.requestWithCallback = function requestWithCallback(url, args, callback)
error: err,
ctx: args.ctx,
req: reqMeta,
res: response,
res: response
});
}
}

function handleRedirect(res) {
let err = null;
if (args.followRedirect && statuses.redirect[res.statusCode]) { // handle redirect
if (args.followRedirect && statuses.redirect[res.statusCode]) {
// handle redirect
args._followRedirectCount = (args._followRedirectCount || 0) + 1;
const location = res.headers.location;
if (!location) {
@@ -398,7 +428,6 @@ exports.requestWithCallback = function requestWithCallback(url, args, callback)
};
}


if (args.gzip) {
if (!options.headers['Accept-Encoding'] && !options.headers['accept-encoding']) {
options.headers['Accept-Encoding'] = 'gzip';
@@ -412,7 +441,7 @@ exports.requestWithCallback = function requestWithCallback(url, args, callback)
// }

// if (!encoding || encoding.toLowerCase() !== 'gzip') {
return cb(null, body, encoding);
return cb(null, body, encoding);
// }

// debug('gunzip %d length body', body.length);
@@ -421,17 +450,15 @@ exports.requestWithCallback = function requestWithCallback(url, args, callback)

const writeStream = args.writeStream;

debug('Request#%d %s %s with headers %j, options.path: %s',
reqId, method, url, options.headers, options.path);
debug('Request#%d %s %s with headers %j, options.path: %s', reqId, method, url, options.headers, options.path);

args.requestUrls.push(url);

function onResponse(res) {
if (timing) {
timing.waiting = Date.now() - requestStartTime;
}
debug('Request#%d %s `req response` event emit: status %d, headers: %j',
reqId, url, res.statusCode, res.headers);
debug('Request#%d %s `req response` event emit: status %d, headers: %j', reqId, url, res.statusCode, res.headers);

if (args.streaming) {
const result = handleRedirect(res);
@@ -448,19 +475,16 @@ exports.requestWithCallback = function requestWithCallback(url, args, callback)
}

res.on('close', function () {
debug('Request#%d %s: `res close` event emit, total size %d',
reqId, url, responseSize);
debug('Request#%d %s: `res close` event emit, total size %d', reqId, url, responseSize);
});

res.on('error', function () {
debug('Request#%d %s: `res error` event emit, total size %d',
reqId, url, responseSize);
debug('Request#%d %s: `res error` event emit, total size %d', reqId, url, responseSize);
});

res.on('aborted', function () {
responseAborted = true;
debug('Request#%d %s: `res aborted` event emit, total size %d',
reqId, url, responseSize);
debug('Request#%d %s: `res aborted` event emit, total size %d', reqId, url, responseSize);
});

if (writeStream) {
@@ -505,9 +529,8 @@ exports.requestWithCallback = function requestWithCallback(url, args, callback)
// done(__err || null, null, res);
// });
if (false) {

} else {
writeStream.on('close', function() {
writeStream.on('close', function () {
debug('Request#%d %s: writeStream close event emitted', reqId, url);
done(__err || null, null, res);
});
@@ -539,8 +562,7 @@ exports.requestWithCallback = function requestWithCallback(url, args, callback)

res.on('end', function () {
const body = Buffer.concat(chunks, responseSize);
debug('Request#%d %s: `res end` event emit, total size %d, _dumped: %s',
reqId, url, responseSize, res._dumped);
debug('Request#%d %s: `res end` event emit, total size %d, _dumped: %s', reqId, url, responseSize, res._dumped);

if (__err) {
// req.abort() after `res data` event emit.
@@ -599,7 +621,8 @@ exports.requestWithCallback = function requestWithCallback(url, args, callback)
if (Array.isArray(args.timeout)) {
connectTimeout = ms(args.timeout[0]);
responseTimeout = ms(args.timeout[1]);
} else { // set both timeout equal
} else {
// set both timeout equal
connectTimeout = responseTimeout = ms(args.timeout);
}
debug('ConnectTimeout: %d, ResponseTimeout: %d', connectTimeout, responseTimeout);
@@ -649,7 +672,7 @@ exports.requestWithCallback = function requestWithCallback(url, args, callback)
}

// environment detection: browser or nodejs
if (typeof(window) === 'undefined') {
if (typeof window === 'undefined') {
// start connect timer just after `request` return, and just in nodejs environment
startConnectTimer();
} else {
@@ -678,7 +701,7 @@ exports.requestWithCallback = function requestWithCallback(url, args, callback)

if (timing) {
// request sent
req.on('finish', function() {
req.on('finish', function () {
timing.requestSent = Date.now() - requestStartTime;
});
}
@@ -698,7 +721,7 @@ exports.requestWithCallback = function requestWithCallback(url, args, callback)

const readyState = socket.readyState;
if (readyState === 'opening') {
socket.once('lookup', function(err, ip, addressType) {
socket.once('lookup', function (err, ip, addressType) {
debug('Request#%d %s lookup: %s, %s, %s', reqId, url, err, ip, addressType);
if (timing) {
timing.dnslookup = Date.now() - requestStartTime;
@@ -707,7 +730,7 @@ exports.requestWithCallback = function requestWithCallback(url, args, callback)
remoteAddress = ip;
}
});
socket.once('connect', function() {
socket.once('connect', function () {
if (timing) {
// socket connected
timing.connected = Date.now() - requestStartTime;