TooTallNate / node-proxy-agent

Maps proxy protocols to `http.Agent` implementations
285 stars 69 forks source link

Error: ERR_INVALID_PROTOCOL when using http.globalAgent #40

Closed L3au closed 1 year ago

L3au commented 5 years ago

Problem

With Node.js version > v10.16.0, code as below will throw error if set http.globalAgent.

RunKit Demo

const http = require('http')
const ProxyAgent = require('proxy-agent')

const proxyUri = process.env.http_proxy || 'http://168.63.43.102:3128'

http.globalAgent = new ProxyAgent(proxyUri)

http.get('http://jsonip.org', onresponse)

function onresponse (res) {
  console.log(res.statusCode, res.headers)
  res.pipe(process.stdout)
}
_http_client.js:119
    throw new ERR_INVALID_PROTOCOL(protocol, expectedProtocol);
    ^

TypeError [ERR_INVALID_PROTOCOL]: Protocol "http:" not supported. Expected "undefined"
    at new ClientRequest (_http_client.js:119:11)
    at request (http.js:42:10)
    at Object.get (http.js:46:13)
    at Object.<anonymous> (/Users/L3au/Program/l3au/assets/index.js:8:6)
    at Module._compile (internal/modules/cjs/loader.js:776:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:787:10)
    at Module.load (internal/modules/cjs/loader.js:653:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
    at Function.Module._load (internal/modules/cjs/loader.js:585:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:829:12)

Still occur if using other request library, e.g. axios, got

axios.get('http://jsonip.org').catch(err => console.error)

Environments

Details

After Node v10.16.0, through http.globalAgent = agent will overwrite the default http agent and can affect all http requests. Consequently, there is assertion to check agent protocol and request protocol, and will throw ERR_INVALID_PROTOCOL if not match.

node/lib/_http_client.js#L106-L121

var protocol = options.protocol || defaultAgent.protocol;
var expectedProtocol = defaultAgent.protocol;
if (this.agent && this.agent.protocol)
  expectedProtocol = this.agent.protocol;

var path;
if (options.path) {
  path = String(options.path);
  if (INVALID_PATH_REGEX.test(path))
    throw new ERR_UNESCAPED_CHARACTERS('Request path');
}

if (protocol !== expectedProtocol) {
  throw new ERR_INVALID_PROTOCOL(protocol, expectedProtocol);
}

To handle this, the simplest way is to set protocol property to agent instance, just like the internal http.Agent does.

Does it make sense to solve the problem? If do, I can create a PR to deal with it.

TooTallNate commented 1 year ago

This code in this repository has been moved to the proxy-agents monorepo, so I am closing this pull request. If you feel that this issue still exists as of the latest release, feel free to open a new issue over there.