UNPKG

@luminati-io/luminati-proxy

Version:

A configurable local proxy for brightdata.com

125 lines (115 loc) 4.06 kB
// LICENSE_CODE ZON ISC 'use strict'; /*jslint node:true, esnext:true es9:true*/ const http = require('http'); const https = require('https'); const etask = require('../util/etask.js'); const date = require('../util/date.js'); const Https_agent = require('./https_agent.js'); const {get_host_port, alarm_throw_msg} = require('./util.js'); const {MIN_TLS} = require('./consts.js'); const E = module.exports; const https_servername = 'brd.superproxy.io'; let tls_connect; E.create_requester = opt=>{ if (opt.proxy_connection_type=='https') return new Https_requester(); return new Http_requester(); }; function http_request(lib){ return function _http_request(ctx, opt){ return lib.request(Object.assign({ host: ctx.host, port: ctx.proxy_port, agent: this.agent, minVersion: MIN_TLS, }, opt)); }; } function*request_socket(_this, parent_task, ctx, opt){ const task = this; const port = isNaN(ctx.domain_port) ? 443 : ctx.domain_port; const request = _this.request(ctx, { method: 'CONNECT', path: ctx.domain+':'+port, headers: ctx.format_headers(ctx.connect_headers), rejectUnauthorized: false, // option passed down to https_agent lpm_username: ctx.cred.username, host_port: get_host_port(ctx), minVersion: MIN_TLS, }); request.on('connect', (res, socket, head)=>task.spawn(etask( function*_on_custom_tls_connect(){ alarm_throw_msg(this, 60*date.ms.SEC, 'tls connect timeout'); this.finally(()=>{ et_tls_socket.return(); }); this.on('uncaught', opt.on_error); ctx.timeline.track('connect'); // no reason to try flex if proxy returned error if (!opt.use_flex_tls || res.statusCode!=200) return task.continue({res, socket, head}); if (!tls_connect) { const flex_tls = require('../../svc/flex_tls/flex_tls.js'); tls_connect = flex_tls.connect; } const et_tls_socket = tls_connect({ host: ctx.domain, socket, http1: true, min_tls: MIN_TLS, ignore_throw_on_close: true, ...opt.flex_tls_reject_unauthorized===true&&{ reject_unauthorized: false, }, }); const flex_tls_socket = yield et_tls_socket; parent_task.once('cancel', ()=>flex_tls_socket.destroy()); flex_tls_socket.once('error', opt.on_flex_tls_err); const conn_socket = flex_tls_socket.socket; conn_socket.once('agentRemove', ()=>{ flex_tls_socket.emit('agentRemove'); }); conn_socket.once('close', ()=>{ flex_tls_socket.unpipe(); flex_tls_socket.end(); flex_tls_socket.emit('agentRemove'); flex_tls_socket.off('error', opt.on_flex_tls_err); }); return task.continue({res, socket: flex_tls_socket, head}); }))); request.on('error', opt.on_error).end(); return yield this.wait(); } function destroy_agents(){ this.agent.destroy(); } function Https_requester(){ this.agent = new Https_agent({ keepAlive: true, keepAliveMsecs: 5000, servername: https_servername, maxCachedSessions: 1000, minVersion: MIN_TLS, maxSockets: 100, maxFreeSockets: 100, timeout: 30000, }); } Https_requester.prototype.request_socket = etask._fn(request_socket); Https_requester.prototype.request = http_request(https); Https_requester.prototype.stop = destroy_agents; function Http_requester(){ this.agent = new http.Agent({ keepAlive: true, keepAliveMsecs: 5000, maxSockets: 100, maxFreeSockets: 100, timeout: 30000, }); } Http_requester.prototype.request_socket = etask._fn(request_socket); Http_requester.prototype.request = http_request(http); Http_requester.prototype.stop = destroy_agents; E.t = {Http_requester, Https_requester};