ฉันจะใช้พร็อกซี http กับ node.js http.Client ได้อย่างไร


143

ฉันต้องการที่จะโทร HTTP ขาออกจาก Node.js http.Clientใช้มาตรฐาน แต่ฉันไม่สามารถเข้าถึงเซิร์ฟเวอร์ระยะไกลได้โดยตรงจากเครือข่ายของฉันและจำเป็นต้องผ่านพร็อกซี

ฉันจะบอกให้ node.js ใช้พร็อกซีได้อย่างไร


1
ฉันมีปัญหาเดียวกัน Node.js อยู่หลังไฟร์วอลล์และฉันไม่สามารถสร้าง HTTPClient ไปยังเว็บไซต์ภายนอกได้
ddallala

คำตอบ:


156

คำตอบของTim Macfarlaneใกล้เคียงกับการใช้พร็อกซี HTTP

การใช้พร็อกซี HTTP (สำหรับคำขอที่ไม่ปลอดภัย) นั้นง่ายมาก คุณเชื่อมต่อกับพร็อกซีและทำการร้องขอตามปกติยกเว้นว่าส่วนพา ธ มี url แบบเต็มและส่วนหัวของโฮสต์ถูกตั้งค่าเป็นโฮสต์ที่คุณต้องการเชื่อมต่อ
Tim ใกล้ชิดกับคำตอบของเขามาก แต่เขาพลาดการตั้งค่าส่วนหัวของโฮสต์อย่างถูกต้อง

var http = require("http");

var options = {
  host: "proxy",
  port: 8080,
  path: "http://www.google.com",
  headers: {
    Host: "www.google.com"
  }
};
http.get(options, function(res) {
  console.log(res);
  res.pipe(process.stdout);
});

สำหรับบันทึกคำตอบของเขาใช้งานได้กับhttp://nodejs.org/แต่นั่นเป็นเพราะเซิร์ฟเวอร์ของพวกเขาไม่สนใจว่าส่วนหัวของโฮสต์ไม่ถูกต้อง


1
มีวิธีใช้ http proxy connect https port หรือไม่? ดูเหมือนจะไม่มีวิธีง่ายๆ
Gohan

@Gohan ดูคำตอบของ Chris ด้านล่างสำหรับตัวอย่างวิธีการเชื่อมต่อกับเซิร์ฟเวอร์ https ผ่านและ http proxy
HairOfTheDog

หากคุณได้รับคำขอที่ไม่ดีให้ใส่เส้นทาง: '/'
Laurent Debricon

9
ฉันจะรวมผู้ใช้พร็อกซีและรหัสผ่านพร็อกซีในบล็อกตัวเลือกได้อย่างไร
Twistleton

สิ่งนี้มีการเปลี่ยนแปลงหรือไม่? แม้จะมีปลายทางสุดท้ายเป็นเซิร์ฟเวอร์ภายในเครื่องอื่นฉันก็ได้รับ404และเซิร์ฟเวอร์ปลายทางไม่เคยได้รับคำขอ ..
OJFord

57

คุณสามารถใช้คำขอได้ฉันเพิ่งพบว่าการใช้พร็อกซีบน node.js นั้นง่ายอย่างไม่น่าเชื่อเพียงแค่มีพารามิเตอร์ "พร็อกซี" ภายนอกเพียงพารามิเตอร์เดียวยิ่งรองรับ HTTPS ผ่านพร็อกซี http

var request = require('request');

request({
  'url':'https://anysite.you.want/sub/sub',
  'method': "GET",
  'proxy':'http://yourproxy:8087'
},function (error, response, body) {
  if (!error && response.statusCode == 200) {
    console.log(body);
  }
})

1
ทำงานสำหรับทั้งสองอย่างhttpและhttpsในกรณีของฉันขอบคุณมาก
Samuel Bushi

ความคิดใด ๆ ที่ทำไมสิ่งนี้ใช้ไม่ได้กับหน้าองค์กรภายใน
keinabel

1
ฉันประหลาดใจที่หน้าองค์กรภายในอยู่หลังพร็อกซี คุณแน่ใจหรือไม่ว่าพร็อกซีไม่ได้ถูกข้ามสำหรับเพจภายใน มันอยู่บน vlan อื่นหรือไม่?
Chanoch

คุณต้องระบุการรับรองความถูกต้องด้วย (จะโพสต์ไว้ที่นี่ถ้าฉันคิดออก)
Igor L.

1
@IgorL. ฉันทำให้มันทำงานกับ Auth และโมดูลคำขอกับheaders: {'Proxy-Authorization': XXXX}
Aaron McKeehan

36

สิ่งหนึ่งที่ต้องใช้เวลาสักพักในการคิดหาใช้ 'http' เพื่อเข้าถึงพร็อกซีแม้ว่าคุณจะพยายามพร็อกซีผ่านเซิร์ฟเวอร์ https ก็ตาม สิ่งนี้ใช้ได้กับฉันโดยใช้ Charles (ตัววิเคราะห์โปรโตคอล osx):

var http = require('http');

http.get ({
    host: '127.0.0.1',
    port: 8888,
    path: 'https://www.google.com/accounts/OAuthGetRequestToken'
}, function (response) {
    console.log (response);
});

1
รหัสด้านบนใช้งานไม่ได้สำหรับฉันและเกี่ยวข้องกับปัญหาgithub.com/joyent/node/issues/2474ตรวจสอบคำตอบของ koichik เราต้องใช้ "วิธีการ": "เชื่อมต่อ" และในเหตุการณ์ "เชื่อมต่อ" เราได้ส่งข้อมูลเส้นทาง .
Palani

16

ดังที่ @Renat กล่าวไว้ที่นี่การรับส่งข้อมูล HTTP แบบพร็อกซีมาในคำขอ HTTP ปกติ ส่งคำขอกับพร็อกซีโดยส่งURL แบบเต็มของปลายทางเป็นเส้นทาง

var http = require ('http');

http.get ({
    host: 'my.proxy.com',
    port: 8080,
    path: 'http://nodejs.org/'
}, function (response) {
    console.log (response);
});

2
ดูเหมือนว่าจะใช้งานได้แม้ว่า Fiddler จะเรียกมันว่าเป็นการละเมิดโปรโตคอลซึ่งบ่งชี้ว่าไม่ใช่คำขอ HTTP ผ่านพร็อกซีที่เหมาะสม ...
Marc

12

ฉันซื้อพร็อกซีเซิร์ฟเวอร์ส่วนตัวหลังจากซื้อฉันได้รับ:

255.255.255.255 // IP address of proxy server
99999 // port of proxy server
username // authentication username of proxy server
password // authentication password of proxy server

และฉันต้องการที่จะใช้มัน คำตอบแรกและคำตอบที่สองใช้ได้กับ http (พร็อกซี) -> http (ปลายทาง) เท่านั้นอย่างไรก็ตามฉันต้องการ http (พร็อกซี) -> https (ปลายทาง)

และสำหรับปลายทาง https จะเป็นการดีกว่าถ้าใช้อุโมงค์ HTTPโดยตรง ผมพบว่าวิธีการแก้ปัญหาที่นี่ รหัสสุดท้าย:

const http = require('http')
const https = require('https')
const username = 'username'
const password = 'password'
const auth = 'Basic ' + Buffer.from(username + ':' + password).toString('base64')

http.request({
  host: '255.255.255.255', // IP address of proxy server
  port: 99999, // port of proxy server
  method: 'CONNECT',
  path: 'kinopoisk.ru:443', // some destination, add 443 port for https!
  headers: {
    'Proxy-Authorization': auth
  },
}).on('connect', (res, socket) => {
  if (res.statusCode === 200) { // connected to proxy server
    https.get({
      host: 'www.kinopoisk.ru',
      socket: socket,    // using a tunnel
      agent: false,      // cannot use a default agent
      path: '/your/url'  // specify path to get from server
    }, (res) => {
      let chunks = []
      res.on('data', chunk => chunks.push(chunk))
      res.on('end', () => {
        console.log('DONE', Buffer.concat(chunks).toString('utf8'))
      })
    })
  }
}).on('error', (err) => {
  console.error('error', err)
}).end()

สิ่งนี้ได้ผลสำหรับฉัน! ขอบคุณมาก! 😄
ไท่

11

คิดว่าฉันจะเพิ่มโมดูลนี้ที่ฉันพบ: https://www.npmjs.org/package/global-tunnelซึ่งทำงานได้ดีสำหรับฉัน (ทำงานได้ทันทีกับรหัสและโมดูลบุคคลที่สามทั้งหมดของฉันโดยมีเพียงรหัสด้านล่าง)

require('global-tunnel').initialize({
  host: '10.0.0.10',
  port: 8080
});

ทำสิ่งนี้เพียงครั้งเดียว http (และ https) ทั้งหมดในแอปพลิเคชันของคุณจะต้องผ่านพร็อกซี

หรือโทร

require('global-tunnel').initialize();

จะใช้http_proxyตัวแปรสภาพแวดล้อม


2
สิ่งนี้ได้ผลสำหรับฉัน! อันที่จริงวิธีนี้คุณแยกพร็อกซีออกจากโค้ดและใช้การกำหนดค่าที่มีอยู่สำหรับ npm! นั่นคือวิธีที่จะไปฉันจะบอกว่า
ผ่าตัดคลอด

@NeelBasu ใช่แล้ว
major-mann

7

แพคเกจ http 'คำขอ' ดูเหมือนจะมีคุณสมบัตินี้:

https://github.com/mikeal/request

ตัวอย่างเช่นอ็อบเจ็กต์คำขอ 'r' ด้านล่างใช้ localproxy เพื่อเข้าถึงคำขอ:

var r = request.defaults({'proxy':'http://localproxy.com'})

http.createServer(function (req, resp) {
  if (req.url === '/doodle.png') {
    r.get('http://google.com/doodle.png').pipe(resp)
  }
})

น่าเสียดายที่ไม่มีค่าเริ่มต้น "global" ดังนั้นผู้ใช้ libs ที่ใช้สิ่งนี้ไม่สามารถแก้ไข proxy ได้เว้นแต่ lib จะผ่านตัวเลือก http ...

HTH คริส


แพ็กเกจ http คำขอทำให้ง่ายต่อการอนุญาตให้รหัสของคุณสลับระหว่างการใช้พร็อกซีและการใช้งานที่ไม่ใช่พร็อกซี (ซึ่งค่อนข้างมีประโยชน์บนแล็ปท็อปของฉัน)
Jon Madison

5

โดยทั่วไปคุณไม่จำเป็นต้องมีการสนับสนุนพร็อกซีอย่างชัดเจน โปรโตคอลพร็อกซีค่อนข้างเรียบง่ายและใช้โปรโตคอล HTTP ปกติ คุณต้องใช้พร็อกซีโฮสต์และพอร์ตของคุณเมื่อเชื่อมต่อกับ HTTPClient ตัวอย่าง (จากเอกสาร node.js):

var http = require('http');
var google = http.createClient(3128, 'your.proxy.host');
var request = google.request('GET', '/',
  {'host': 'www.google.com'});
request.end();
...

โดยพื้นฐานแล้วคุณเชื่อมต่อกับพร็อกซีของคุณ แต่ส่งคำขอไปที่ "http://www.google.com"


3
http.createClient เลิกใช้งานแล้ว Tim Macfarlane กำลังใช้ http ที่ใหม่กว่าได้รับด้านล่าง
sami

1
นี้จะเห็นได้ชัดว่าไม่ทำงานร่วมกับ Node.js ณ v5.6 ขณะที่พวกเขาได้ลบcreateClient
Marc

5

ในกรณีที่คุณต้องการใช้การอนุญาตพื้นฐานสำหรับผู้ให้บริการพร็อกซีของคุณให้ใช้สิ่งต่อไปนี้:

var http = require("http");

var options = {
    host:       FarmerAdapter.PROXY_HOST,
    port:       FarmerAdapter.PROXY_PORT,
    path:       requestedUrl,
    headers:    {
        'Proxy-Authorization':  'Basic ' + new Buffer(FarmerAdapter.PROXY_USER + ':' + FarmerAdapter.PROXY_PASS).toString('base64')
    }
};

var request = http.request(options, function(response) {
    var chunks = [];
    response.on('data', function(chunk) {
        chunks.push(chunk);
    });
    response.on('end', function() {
        console.log('Response', Buffer.concat(chunks).toString());
    });
});

request.on('error', function(error) {
    console.log(error.message);
});

request.end();

1
ฉันจะหา "FarmerAdapter" ได้ที่ไหน
Manjeet

3

โหนดควรรองรับการใช้ตัวแปรสภาพแวดล้อม http_proxy - ดังนั้นจึงเป็นแบบข้ามแพลตฟอร์มและทำงานบนการตั้งค่าระบบแทนที่จะต้องกำหนดค่าต่อแอปพลิเคชัน

การใช้โซลูชันที่ให้มาฉันขอแนะนำสิ่งต่อไปนี้:

Coffeescript

get_url = (url, response) ->
  if process.env.http_proxy?
    match = process.env.http_proxy.match /^(http:\/\/)?([^:\/]+)(:([0-9]+))?/i
    if match
      http.get { host: match[2], port: (if match[4]? then match[4] else 80), path: url }, response
      return
  http.get url, response

Javascript

get_url = function(url, response) {
  var match;
  if (process.env.http_proxy != null) {
    match = process.env.http_proxy.match(/^(http:\/\/)?([^:\/]+)(:([0-9]+))?/i);
    if (match) {
      http.get({
        host: match[2],
        port: (match[4] != null ? match[4] : 80),
        path: url
      }, response);
      return;
    }
  }
  return http.get(url, response);
};

การใช้งาน หากต้องการใช้วิธีนี้ให้แทนที่ http.get อย่างมีประสิทธิภาพเช่นต่อไปนี้เขียนหน้าดัชนีของ google ไปยังไฟล์ที่เรียกว่า test.htm:

file = fs.createWriteStream path.resolve(__dirname, "test.htm")
get_url "http://www.google.com.au/", (response) ->
  response.pipe file
  response.on "end", ->
    console.log "complete"

การตั้งค่า http_proxy ดูเหมือนจะไม่มีผลใด ๆ เมื่อเรียกใช้ Node บน Windows
EricLaw

ควรทำงานภายใต้ Windows (นั่นคือระบบหลักที่ฉันใช้) ตรวจสอบให้แน่ใจว่าหลังจากที่คุณได้ตั้งค่าที่คุณได้รีเซ็ตเซสชันเทอร์มินัลแล้ว (หากตั้งค่าผ่านแผงควบคุมและไม่ได้ตั้งค่าไว้) คุณควรจะตรวจสอบได้ว่าตั้งค่าถูกต้องโดยใช้ echo% HTTP_PROXY% หรือดีกว่านั้นคุณควรใช้โหนดเอง node -e "console.log (process.env.http_proxy);" สิ่งนี้ใช้ได้ผลสำหรับฉันใน Windows ขอให้โชคดี
Luke

1

คำตอบของ Imskull เกือบจะได้ผลสำหรับฉัน แต่ฉันต้องทำการเปลี่ยนแปลงบางอย่าง การเปลี่ยนแปลงที่แท้จริงเพียงอย่างเดียวคือการเพิ่มชื่อผู้ใช้รหัสผ่านและการตั้งค่าปฏิเสธไม่ได้รับอนุญาตเป็นเท็จ ฉันไม่สามารถแสดงความคิดเห็นได้ดังนั้นฉันจึงใส่คำตอบนี้ไว้

หากคุณเรียกใช้โค้ดคุณจะได้รับชื่อของเรื่องราวปัจจุบันใน Hacker News ตามบทช่วยสอนนี้: http://smalljs.org/package-managers/npm/

var cheerio = require('cheerio');
var request = require('request');

request({
    'url': 'https://news.ycombinator.com/',
    'proxy': 'http://Username:Password@YourProxy:Port/',
    'rejectUnauthorized': false
}, function(error, response, body) {
    if (!error && response.statusCode == 200) {
        if (response.body) {
            var $ = cheerio.load(response.body);
            $('td.title a').each(function() {
                console.log($(this).text());
            });
       }
    } else {
        console.log('Error or status not equal 200.');
    }
});

1

ฉันคิดว่ามีทางเลือกอื่นที่ดีกว่าสำหรับคำตอบในปี 2019 เราสามารถใช้global-tunnel-ngแพคเกจเพื่อเริ่มต้นพร็อกซีและไม่ก่อให้เกิดมลพิษต่อรหัสhttpหรือhttpsตามทุกที่ ก่อนอื่นให้ติดตั้งglobal-tunnel-ngแพ็คเกจ:

npm install global-tunnel-ng

จากนั้นเปลี่ยนการใช้งานของคุณเพื่อเตรียมใช้งานพร็อกซีหากจำเป็นดังนี้

const globalTunnel = require('global-tunnel-ng');

globalTunnel.initialize({
  host: 'proxy.host.name.or.ip',
  port: 8080
});

0

อาจไม่ใช่ซับเดียวที่คุณคาดหวัง แต่คุณสามารถดูได้ที่http://github.com/nodejitsu/node-http-proxyเนื่องจากอาจทำให้เข้าใจถึงวิธีการใช้แอปของคุณกับ http ลูกค้า


1
สิ่งนี้มีประโยชน์อย่างไร
Jerinaw

0

http://groups.google.com/group/nodejs/browse_thread/thread/d5aadbcaa00c3f7/12ebf01d7ec415c3?lnk=gst&q=proxy#12ebf01d7ec415c3

จากคำตอบจากเธรดนี้ดูเหมือนว่าคุณสามารถใช้proxychains เพื่อรัน node.js ผ่านพร็อกซีเซิร์ฟเวอร์:
$ proxychains /path/to/node application.js

โดยส่วนตัวแล้วฉันไม่สามารถติดตั้งเวอร์ชันproxychainsใด ๆบนสภาพแวดล้อมCygwin / Windowsจึงไม่สามารถทดสอบได้

นอกจากนี้พวกเขายังพูดคุยเกี่ยวกับการใช้connect-proxyแต่ฉันไม่พบเอกสารเกี่ยวกับวิธีการทำเช่นนี้

ในระยะสั้นฉันยังติดอยู่ แต่อาจมีใครบางคนสามารถใช้ข้อมูลนี้เพื่อหาวิธีแก้ไขปัญหาที่เหมาะสม


อัปเดต: หลังจากมีการตรวจสอบพบว่าฉันไม่สามารถสร้างพร็อกซีเชนบน CygWin ได้เนื่องจากไม่รองรับ RTLD_NEXT
ddallala


0

ใช้ 'https-proxy-agent' เช่นนี้

var HttpsProxyAgent = require('https-proxy-agent');
var proxy = process.env.https_proxy || 'other proxy address';
var agent = new HttpsProxyAgent(proxy);

options = {
    //...
    agent : agent
}

https.get(options, (res)=>{...});

0

หากคุณมีโครงร่างการพิสูจน์ตัวตนพื้นฐาน httpคุณต้องสร้างสตริง base64 จากmyuser:mypasswordนั้นเพิ่ม "พื้นฐาน" ในตอนต้น นั่นคือค่าของส่วนหัวProxy-Authorizationนี่คือตัวอย่าง:

var Http = require('http');

var req = Http.request({
    host: 'myproxy.com.zx',
    port: 8080,
    headers:{"Proxy-Authorization": "Basic bXl1c2VyOm15cGFzc3dvcmQ="},
    method: 'GET',
    path: 'http://www.google.com/'
    }, function (res) {
        res.on('data', function (data) {
        console.log(data.toString());
    });
});

req.end();

ใน nodejs คุณสามารถใช้Bufferเพื่อเข้ารหัส

var encodedData = Buffer.from('myuser:mypassword').toString('base64');

console.log(encodedData);

เช่นในเบราว์เซอร์คุณสามารถเข้ารหัสใน base64 โดยใช้btoa ()ซึ่งมีประโยชน์ในการร้องขอ ajax ในเบราว์เซอร์ที่ไม่มีการตั้งค่าพร็อกซีที่ดำเนินการตามคำขอโดยใช้พร็อกซี

var encodedData = btoa('myuser:mypassword')

console.log(encodedData);

จะค้นหาโครงการใดที่ยอมรับพร็อกซีเซิร์ฟเวอร์ได้อย่างไร

หากเราไม่ได้กำหนดค่า DNS ที่กำหนดเอง (ซึ่งจะส่งข้อมูลบางอย่างเช่น ERR_NAME_NOT_RESOLVED) เมื่อเราดำเนินการตามคำขอการตอบกลับ (รหัส 407) ควรแจ้งในส่วนหัวการตอบกลับซึ่งรูปแบบการตรวจสอบสิทธิ์ HTTP ที่พร็อกซีใช้อยู่


0

เพียงแค่รัน nodejs ด้วย proxy wrapper เช่น tsocks tsocks node myscript.js

โซลูชันดั้งเดิม: ทำการ ร้องขอ http ผ่านพร็อกซี SOCKS5 ใน NodeJS

ข้อมูลเพิ่มเติม: https://www.binarytides.com/proxify-applications-with-tsocks-and-proxychains-on-ubuntu/

สำหรับ Windows: /superuser/319516/how-to-force-any-program-to-use-socks

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.