UNPKG

@luminati-io/luminati-proxy

Version:

A configurable local proxy for luminati.io

172 lines (161 loc) 6.09 kB
// LICENSE_CODE ZON ISC 'use strict'; /*zlint node, br*/ (function(){ var define; var is_node_ff = typeof module=='object' && module.exports; if (!is_node_ff) define = self.define; else define = require('./require_node.js').define(module, '../'); define(['jquery', '/util/etask.js', '/util/date.js', '/util/escape.js', '/util/zerr.js', 'events'], function($, etask, date, zescape, zerr, events){ var assign = Object.assign; var E = function(){ return E.send.apply(this, arguments); }; E.send = function(opt){ var timeout = opt.timeout||20*date.ms.SEC, slow = opt.slow||2*date.ms.SEC; var retry = opt.retry, data = opt.data, qs = zescape.qs(opt.qs); var url = zescape.uri(opt.url, qs), perr = opt.perr; // opt.type is deprecated var method = opt.method||opt.type||'GET'; var data_type = opt.json ? 'json' : 'text'; var t0 = Date.now(); var ajopt, xhr; zerr.debug('ajax('+data_type+') url '+url+' retry '+retry); return etask([function(){ ajopt = {type: method, url: url, headers: assign({}, opt.headers), dataType: data_type, data: data, timeout: timeout, xhrFields: {}}; if (opt.content_type) ajopt.contentType = opt.content_type; if (opt.with_credentials) ajopt.xhrFields.withCredentials = true; if (opt.onprogress) ajopt.xhrFields.onprogress = opt.onprogress; if (opt.onuploadprogress) { ajopt.xhr = function(){ var _xhr = $.ajaxSettings.xhr(); _xhr.upload.onprogress = opt.onuploadprogress; return _xhr; }; } if (opt.multipart) { ajopt.contentType = false; ajopt.processData = false; delete ajopt.dataType; } if (opt.async!==undefined) ajopt.async = opt.async; E.ajopt_modifiers.forEach(function(modifier){ modifier(ajopt); }); xhr = $.ajax(ajopt); var _this = this; xhr.done(function(v){ _this.continue(v); }); xhr.fail(function(_xhr, status_text, err){ if (data_type=='json' && _xhr && _xhr.status==200 && ['', 'ok', 'OK'].includes(_xhr.responseText)) { _this.continue(null); return; } if (!err && _xhr && _xhr.responseText && !_xhr.responseJSON) err = _xhr.responseText; _this.throw(err instanceof Error ? err : new Error(''+err)); }); return this.wait(); }, function catch$(err){ xhr = xhr||{}; zerr('ajax('+data_type+') failed url '+url+' data '+ zerr.json(data).substr(0, 200)+' status: '+xhr.status+' '+ xhr.statusText+'\nresponseText: '+ (xhr.responseText||'').substr(0, 200)); if (retry && (!opt.should_retry||opt.should_retry(err, xhr, ajopt))) return this.return(E.send(assign({}, opt, {retry: retry-1}))); if (xhr.statusText=='timeout') E.events.emit('timeout', this); if (xhr.status==403) E.events.emit('unauthorized', this, xhr); if (xhr.status==500) E.events.emit('unhandledException', this, xhr); if (opt.no_throw) { return { err: err, url: url, method: method, status: +xhr.status || 0, data: get_res_data(xhr), xhr: xhr, // legacy error: xhr.statusText||'no_status', message: xhr.responseText, }; } err.xhr_info = {url: url, method: method, status: xhr.status, data: get_res_data(xhr), response_text: xhr.responseText}; err.x_error = xhr.getResponseHeader('X-Luminati-Error') || xhr.getResponseHeader('X-Hola-Error'); throw err; }, function(_data){ var t = Date.now()-t0; zerr[t>slow ? 'err' : 'debug']( 'ajax('+data_type+') '+(t>slow ? 'SLOW ' : 'ok ')+t+'ms url '+url); if (t>slow && perr) perr({id: 'be_ajax_slow', info: t+'ms '+url}); if (E.do_op) E.do_op(_data&&_data.do_op); if (opt.restore_dates) restore_dates(_data); return this.return(_data); }, function abort(){ // reachable only via E.abort xhr.abort(); }]); }; E.abort = function(aj){ aj.goto('abort'); }; ['GET', 'POST', 'PUT', 'DELETE'].forEach(function(m){ E[m.toLowerCase()] = function(url, opt){ url = typeof url=='string' ? {url: url} : url; opt = assign({method: m, json: 1}, url, opt); if (!{get: 1, delete: 1}[opt.method.toLowerCase()] && opt.data!=null && typeof opt.data!='string') { opt.content_type = opt.content_type||'application/json'; if (opt.content_type.startsWith('application/json')) opt.data = JSON.stringify(opt.data); } return E.send(opt); }; }); E.json = function(opt){ return E.send(assign({}, opt, {json: 1})); }; E.events = new events.EventEmitter(); E.ajopt_modifiers = []; // -- internal utils --- function get_res_data(xhr){ if (xhr.responseJSON!=null && xhr.responseJSON!=='') return xhr.responseJSON; var content_type = xhr.getResponseHeader('content-type')||''; if (xhr.responseText && content_type.includes('application/json')) { try { return JSON.parse(xhr.responseText); } catch(e){ } } return xhr.responseText||''; } function restore_dates(data){ if (!data || typeof data!='object') return; for (var key in data) { if (!data.hasOwnProperty(key)) continue; var val = data[key]; if (typeof val=='string' && date_rx.test(val)) data[key] = new Date(val); else if (val && typeof val=='object') restore_dates(val); } } var date_rx = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+([+-]\d{2}:\d{2}|Z)$/; return E; }); }());