UNPKG

als-request

Version:

versatile HTTP client offering enhanced features for Node.js with functionality for speed limitation with events, CORS management, stream support, automatic data preparation, error and response handling, and more

125 lines (114 loc) 4.23 kB
const mime = require('./mime') const canResponse = require('./can-response') const { createWriteStream } = require('fs') const jsonGetter = require('./json-getter') const errorHandler = require('../error-handler') class Response { constructor(request,dl) { this.request = request this.dl = dl this.promise = new Promise((resolve, reject) => { this.resolve = resolve this.reject = reject }) } stream(path) { return this.execResponse(() => { let stream = createWriteStream(path) this.request.res.pipe(stream) stream.on('finish', () => this._end()) stream.on('error', error => this.reject({error,errors:this.request.errors})) }) } $response() { return this.execResponse(() => { jsonGetter(this.response) this.request.res.on('end', () => { let buffer = Buffer.concat(this.chunks); if (buffer) this.response.data = buffer.toString("utf8"); this._end(); }); }) } execResponse(fn) { const {url,req,onResponse,urlObj,errors,requester,options} = this.request if(!canResponse(req,requester,this.processing,url,errors)) return {errors,error:null} this.processing = true const _redirects = [] req.on('redirect', (res, options) => { _redirects.push(`${options.hostname}${options.path}`) }); req.on('error', error => { this.request.errors.push(errorHandler({code:'REQERR',url:this.url,err:error})) const idleTime = parseInt(Date.now() - options.initTime) this.reject({idleTime,error:'REQERR',url,errors,noResponse:true,_redirects,urlObj}) }) req.on('response', () => { this.prepareResponse(_redirects) this.download = true if(typeof onResponse === 'function') onResponse(this.request,this) this.request.res.on('error', error => this.reject(error)); this.chunks = []; if(this.download) { this.loadTime = Date.now() this.waitTime = 0 if(this.dl) this.dl.startChecking(this) this.request.res.on('data', chunk => this.chunks.push(chunk)); fn() } else this.resolve(this.response) }); return this.promise; } prepareResponse(_redirects) { const {options,res,req,url,urlObj,errors} = this.request const {initTime} = options let { rawHeaders, method, headers, client, socket, responseUrl, statusCode } = res this.response = { status: statusCode, rawHeaders, responseUrl, headers, client, socket,urlObj,_redirects, idleTime: parseInt(Date.now() - initTime), error: null, errors,_redirects:[] } this.addGetters(headers,url,this) } addGetters(headers,url,self) { Object.defineProperty(this.response, 'type', {get() {return mime(headers,url)}}); Object.defineProperty(this.response, 'size', { get() { if(headers) { if(headers['content-length']) return headers['content-length'] } return self.chunks.length } }); } _end() { const {loadTime,waitTime=0} = this if(loadTime) { this.loadTime = Date.now() - loadTime - waitTime this.response.loadTime = parseInt(this.loadTime) this.response.waitTime = waitTime if(this.dl) this.dl.remove(this) } this.resolve(this.response) } pause() { const {onPause} = this.request if(typeof onPause == 'function') onPause(this.request,this) this.request.res.pause() this.paused = true this.waitStartTime = Date.now() } resume() { const {onResume} = this.request if(typeof onResume == 'function') onResume(this.request,this) this.request.res.resume() this.paused = false if(this.waitStartTime) { this.waitTime += Date.now() - this.waitStartTime this.waitStartTime = null; // reset waitStartTim } } } module.exports = Response