tomas / needle

Nimble, streamable HTTP client for Node.js. With proxy, iconv, cookie, deflate & multipart support.
https://www.npmjs.com/package/needle
MIT License
1.63k stars 236 forks source link

Error 500 for corporate proxy #321

Open eavdmeer opened 4 years ago

eavdmeer commented 4 years ago

I ran into an error installing the sqlite3 node module where on one account it would install fine, while on another it doesn't. The difference turned out to be one using request, while the other, failing one, used needle. All use the same http_proxy URL from the environment.

node-pre-gyp WARN Using needle for node-pre-gyp https download node-pre-gyp info check checked for "/tmp/webtest/node_modules/sqlite3/lib/binding/node-v64-linux-x64/node_sqlite3.node" (not found) node-pre-gyp http GET https://mapbox-node-binary.s3.amazonaws.com/sqlite3/v4.2.0/node-v64-linux-x64.tar.gz node-pre-gyp verb download using proxy url: "http://giba-proxy.wps.ing.net:8090" node-pre-gyp http 500 https://mapbox-node-binary.s3.amazonaws.com/sqlite3/v4.2.0/node-v64-linux-x64.tar.gz node-pre-gyp WARN Tried to download(500): https://mapbox-node-binary.s3.amazonaws.com/sqlite3/v4.2.0/node-v64-linux-x64.tar.gz node-pre-gyp WARN Pre-built binaries not found for sqlite3@4.2.0 and node@10.21.0 (node-v64 ABI, glibc) (falling back to source compile with node-gyp) node-pre-gyp http 500 status code downloading tarball https://mapbox-node-binary.s3.amazonaws.com/sqlite3/v4.2.0/node-v64-linux-x64.tar.gz

The account where it works shows this;

node-pre-gyp WARN Using request for node-pre-gyp https download node-pre-gyp info check checked for "/appl/gmdb/mdbdev/home/qy69gz/work/bla/new/node_modules/sqlite3/lib/binding/node-v64-linux-x64/node_sqlite3.node" (not found) node-pre-gyp http GET https://mapbox-node-binary.s3.amazonaws.com/sqlite3/v4.2.0/node-v64-linux-x64.tar.gz node-pre-gyp verb download using proxy url: "http://giba-proxy.wps.ing.net:8090/" node-pre-gyp http 200 https://mapbox-node-binary.s3.amazonaws.com/sqlite3/v4.2.0/node-v64-linux-x64.tar.gz node-pre-gyp info install unpacking node-v64-linux-x64/node_sqlite3.node node-pre-gyp info tarball done parsing tarball

I built a simple code example, using needle, request and https/https-proxy-agent.

const fs = require('fs');
const https = require("https");
const needle = require('needle');
const process = require('process');
const Proxy = require("https-proxy-agent");
const request = require('request');
const url = require("url");

const target = 'https://mapbox-node-binary.s3.amazonaws.com/sqlite3/v4.2.0/node-v64-linux-x64.tar.gz';

var
  options,
  proxy,
  req;

// Raw https with https-proxy agent
options = url.parse(target);
options.agent = new Proxy(process.env.http_proxy);
req = https.get(options, response =>
{
  console.log(`https: statusCode: ${response && response.statusCode}`);
});
req.on("error", err =>
{
  console.log(`https: error in request; ${err.message}`);
});

// Deprecated request with forced proxy option
options = { proxy: process.env.http_proxy };
proxy = request.defaults(options);
proxy.get(target, options, (err, response, body) =>
{
  if (err)
  {
    console.log(`request: error in request; ${err.message}`);
    return;
  }

  console.log(`request statusCode: ${response && response.statusCode}`);
});

// Needle with proxy option
options = { proxy: process.env.http_proxy };
needle.get(target, options, (err, response, body) =>
{
  if (err)
  {
    console.log(`needle: error in request; ${err.message}`);
    return;
  }

  console.log(`needle: statusCode: ${response && response.statusCode}`);
});

The resulting HTTP codes are:

needle: statusCode: 500
https: statusCode: 200
request statusCode: 200

The same URL works fine in curl and wget, which both use the same http_proxy variable.

The proxy responds with the following:

Handshake failed
The SSL handshake could not be performed
Can't initialize server context:handshakefailed:server state 1:state 9:Application response 500 handshakefailed

Basically, this issue is preventing me from upgrading to node v10 as I need the binary part of the sqlite3 lib. Without that, I'm stuck on v6. The build fallback fails as this is an older version of the C-compiler that cannot be upgraded.

tomas commented 4 years ago

Is the proxy a HTTPS endpoint or plain HTTP?

eavdmeer commented 4 years ago

I'm not sure. The proxy URL is http, not https. Is there any way to find out?

tomas commented 4 years ago

You can use opessl's s_client:

openssl s_client -connect server.com:443 (or whatever port it's listening on)
eavdmeer commented 4 years ago

CONNECTED(00000003) 140655881995944:error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol:s23_clnt.c:797: --- no peer certificate available --- No client certificate CA names sent --- SSL handshake has read 7 bytes and written 305 bytes --- New, (NONE), Cipher is (NONE) Secure Renegotiation IS NOT supported Compression: NONE Expansion: NONE No ALPN negotiated SSL-Session:     Protocol  : TLSv1.2     Cipher    : 0000     Session-ID:     Session-ID-ctx:     Master-Key:     Key-Arg   : None     PSK identity: None     PSK identity hint: None     SRP username: None     Start Time: 1591373184     Timeout   : 300 (sec)     Verify return code: 0 (ok) ---

tomas commented 4 years ago

Looks like the endpoint isn't HTTPS. Does the proxy url start with https://? That might be causing the issue.

eavdmeer commented 4 years ago

The proxy URL is in the logs I included. It starts with http://

eavdmeer commented 4 years ago

Just to be clear. In this command:

openssl s_client -connect server.com:443 (or whatever port it's listening on)

Do you want me to connect to the actual endpoint or the proxy itself?

openssl will not connect to the endpoint, because I'm on an Intranet that does not provide DNS for external websites like the host I'm connecting to:

mapbox-node-binary.s3.amazonaws.com

The installed openssl version is 1.0.x, so it does not support the -proxy option