Giter Site home page Giter Site logo

node-http-proxy's Introduction

node-http-proxy Build Status codecov

node-http-proxy is an HTTP programmable proxying library that supports websockets. It is suitable for implementing components such as reverse proxies and load balancers.

Table of Contents

Installation

npm install http-proxy --save

Back to top

Upgrading from 0.8.x ?

Click here

Back to top

Core Concept

A new proxy is created by calling createProxyServer and passing an options object as argument (valid properties are available here)

var httpProxy = require('http-proxy');

var proxy = httpProxy.createProxyServer(options); // See (†)

†Unless listen(..) is invoked on the object, this does not create a webserver. See below.

An object will be returned with four methods:

  • web req, res, [options] (used for proxying regular HTTP(S) requests)
  • ws req, socket, head, [options] (used for proxying WS(S) requests)
  • listen port (a function that wraps the object in a webserver, for your convenience)
  • close [callback] (a function that closes the inner webserver and stops listening on given port)

It is then possible to proxy requests by calling these functions

http.createServer(function(req, res) {
  proxy.web(req, res, { target: 'http://mytarget.com:8080' });
});

Errors can be listened on either using the Event Emitter API

proxy.on('error', function(e) {
  ...
});

or using the callback API

proxy.web(req, res, { target: 'http://mytarget.com:8080' }, function(e) { ... });

When a request is proxied it follows two different pipelines (available here) which apply transformations to both the req and res object. The first pipeline (incoming) is responsible for the creation and manipulation of the stream that connects your client to the target. The second pipeline (outgoing) is responsible for the creation and manipulation of the stream that, from your target, returns data to the client.

Back to top

Use Cases

Setup a basic stand-alone proxy server

var http = require('http'),
    httpProxy = require('http-proxy');
//
// Create your proxy server and set the target in the options.
//
httpProxy.createProxyServer({target:'http://localhost:9000'}).listen(8000); // See (†)

//
// Create your target server
//
http.createServer(function (req, res) {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.write('request successfully proxied!' + '\n' + JSON.stringify(req.headers, true, 2));
  res.end();
}).listen(9000);

†Invoking listen(..) triggers the creation of a web server. Otherwise, just the proxy instance is created.

Back to top

Setup a stand-alone proxy server with custom server logic

This example shows how you can proxy a request using your own HTTP server and also you can put your own logic to handle the request.

var http = require('http'),
    httpProxy = require('http-proxy');

//
// Create a proxy server with custom application logic
//
var proxy = httpProxy.createProxyServer({});

//
// Create your custom server and just call `proxy.web()` to proxy
// a web request to the target passed in the options
// also you can use `proxy.ws()` to proxy a websockets request
//
var server = http.createServer(function(req, res) {
  // You can define here your custom logic to handle the request
  // and then proxy the request.
  proxy.web(req, res, { target: 'http://127.0.0.1:5050' });
});

console.log("listening on port 5050")
server.listen(5050);

Back to top

Setup a stand-alone proxy server with proxy request header re-writing

This example shows how you can proxy a request using your own HTTP server that modifies the outgoing proxy request by adding a special header.

var http = require('http'),
    httpProxy = require('http-proxy');

//
// Create a proxy server with custom application logic
//
var proxy = httpProxy.createProxyServer({});

// To modify the proxy connection before data is sent, you can listen
// for the 'proxyReq' event. When the event is fired, you will receive
// the following arguments:
// (http.ClientRequest proxyReq, http.IncomingMessage req,
//  http.ServerResponse res, Object options). This mechanism is useful when
// you need to modify the proxy request before the proxy connection
// is made to the target.
//
proxy.on('proxyReq', function(proxyReq, req, res, options) {
  proxyReq.setHeader('X-Special-Proxy-Header', 'foobar');
});

var server = http.createServer(function(req, res) {
  // You can define here your custom logic to handle the request
  // and then proxy the request.
  proxy.web(req, res, {
    target: 'http://127.0.0.1:5050'
  });
});

console.log("listening on port 5050")
server.listen(5050);

Back to top

Modify a response from a proxied server

Sometimes when you have received a HTML/XML document from the server of origin you would like to modify it before forwarding it on.

Harmon allows you to do this in a streaming style so as to keep the pressure on the proxy to a minimum.

Back to top

Setup a stand-alone proxy server with latency

var http = require('http'),
    httpProxy = require('http-proxy');

//
// Create a proxy server with latency
//
var proxy = httpProxy.createProxyServer();

//
// Create your server that makes an operation that waits a while
// and then proxies the request
//
http.createServer(function (req, res) {
  // This simulates an operation that takes 500ms to execute
  setTimeout(function () {
    proxy.web(req, res, {
      target: 'http://localhost:9008'
    });
  }, 500);
}).listen(8008);

//
// Create your target server
//
http.createServer(function (req, res) {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.write('request successfully proxied to: ' + req.url + '\n' + JSON.stringify(req.headers, true, 2));
  res.end();
}).listen(9008);

Back to top

Using HTTPS

You can activate the validation of a secure SSL certificate to the target connection (avoid self-signed certs), just set secure: true in the options.

HTTPS -> HTTP
//
// Create the HTTPS proxy server in front of a HTTP server
//
httpProxy.createServer({
  target: {
    host: 'localhost',
    port: 9009
  },
  ssl: {
    key: fs.readFileSync('valid-ssl-key.pem', 'utf8'),
    cert: fs.readFileSync('valid-ssl-cert.pem', 'utf8')
  }
}).listen(8009);
HTTPS -> HTTPS
//
// Create the proxy server listening on port 443
//
httpProxy.createServer({
  ssl: {
    key: fs.readFileSync('valid-ssl-key.pem', 'utf8'),
    cert: fs.readFileSync('valid-ssl-cert.pem', 'utf8')
  },
  target: 'https://localhost:9010',
  secure: true // Depends on your needs, could be false.
}).listen(443);
HTTP -> HTTPS (using a PKCS12 client certificate)
//
// Create an HTTP proxy server with an HTTPS target
//
httpProxy.createProxyServer({
  target: {
    protocol: 'https:',
    host: 'my-domain-name',
    port: 443,
    pfx: fs.readFileSync('path/to/certificate.p12'),
    passphrase: 'password',
  },
  changeOrigin: true,
}).listen(8000);

Back to top

Proxying WebSockets

You can activate the websocket support for the proxy using ws:true in the options.

//
// Create a proxy server for websockets
//
httpProxy.createServer({
  target: 'ws://localhost:9014',
  ws: true
}).listen(8014);

Also you can proxy the websocket requests just calling the ws(req, socket, head) method.

//
// Setup our server to proxy standard HTTP requests
//
var proxy = new httpProxy.createProxyServer({
  target: {
    host: 'localhost',
    port: 9015
  }
});
var proxyServer = http.createServer(function (req, res) {
  proxy.web(req, res);
});

//
// Listen to the `upgrade` event and proxy the
// WebSocket requests as well.
//
proxyServer.on('upgrade', function (req, socket, head) {
  proxy.ws(req, socket, head);
});

proxyServer.listen(8015);

Back to top

Options

httpProxy.createProxyServer supports the following options:

  • target: url string to be parsed with the url module

  • forward: url string to be parsed with the url module

  • agent: object to be passed to http(s).request (see Node's https agent and http agent objects)

  • ssl: object to be passed to https.createServer()

  • ws: true/false, if you want to proxy websockets

  • xfwd: true/false, adds x-forward headers

  • secure: true/false, if you want to verify the SSL Certs

  • toProxy: true/false, passes the absolute URL as the path (useful for proxying to proxies)

  • prependPath: true/false, Default: true - specify whether you want to prepend the target's path to the proxy path

  • ignorePath: true/false, Default: false - specify whether you want to ignore the proxy path of the incoming request (note: you will have to append / manually if required).

  • localAddress: Local interface string to bind for outgoing connections

  • changeOrigin: true/false, Default: false - changes the origin of the host header to the target URL

  • preserveHeaderKeyCase: true/false, Default: false - specify whether you want to keep letter case of response header key

  • auth: Basic authentication i.e. 'user:password' to compute an Authorization header.

  • hostRewrite: rewrites the location hostname on (201/301/302/307/308) redirects.

  • autoRewrite: rewrites the location host/port on (201/301/302/307/308) redirects based on requested host/port. Default: false.

  • protocolRewrite: rewrites the location protocol on (201/301/302/307/308) redirects to 'http' or 'https'. Default: null.

  • cookieDomainRewrite: rewrites domain of set-cookie headers. Possible values:

    • false (default): disable cookie rewriting
    • String: new domain, for example cookieDomainRewrite: "new.domain". To remove the domain, use cookieDomainRewrite: "".
    • Object: mapping of domains to new domains, use "*" to match all domains. For example keep one domain unchanged, rewrite one domain and remove other domains:
      cookieDomainRewrite: {
        "unchanged.domain": "unchanged.domain",
        "old.domain": "new.domain",
        "*": ""
      }
      
  • cookiePathRewrite: rewrites path of set-cookie headers. Possible values:

    • false (default): disable cookie rewriting
    • String: new path, for example cookiePathRewrite: "/newPath/". To remove the path, use cookiePathRewrite: "". To set path to root use cookiePathRewrite: "/".
    • Object: mapping of paths to new paths, use "*" to match all paths. For example, to keep one path unchanged, rewrite one path and remove other paths:
      cookiePathRewrite: {
        "/unchanged.path/": "/unchanged.path/",
        "/old.path/": "/new.path/",
        "*": ""
      }
      
  • headers: object with extra headers to be added to target requests.

  • proxyTimeout: timeout (in millis) for outgoing proxy requests

  • timeout: timeout (in millis) for incoming requests

  • followRedirects: true/false, Default: false - specify whether you want to follow redirects

  • selfHandleResponse true/false, if set to true, none of the webOutgoing passes are called and it's your responsibility to appropriately return the response by listening and acting on the proxyRes event

  • buffer: stream of data to send as the request body. Maybe you have some middleware that consumes the request stream before proxying it on e.g. If you read the body of a request into a field called 'req.rawbody' you could restream this field in the buffer option:

    'use strict';
    
    const streamify = require('stream-array');
    const HttpProxy = require('http-proxy');
    const proxy = new HttpProxy();
    
    module.exports = (req, res, next) => {
    
      proxy.web(req, res, {
        target: 'http://localhost:4003/',
        buffer: streamify(req.rawBody)
      }, next);
    
    };
    

NOTE: options.ws and options.ssl are optional. options.target and options.forward cannot both be missing

If you are using the proxyServer.listen method, the following options are also applicable:

  • ssl: object to be passed to https.createServer()
  • ws: true/false, if you want to proxy websockets

Back to top

Listening for proxy events

  • error: The error event is emitted if the request to the target fail. We do not do any error handling of messages passed between client and proxy, and messages passed between proxy and target, so it is recommended that you listen on errors and handle them.
  • proxyReq: This event is emitted before the data is sent. It gives you a chance to alter the proxyReq request object. Applies to "web" connections
  • proxyReqWs: This event is emitted before the data is sent. It gives you a chance to alter the proxyReq request object. Applies to "websocket" connections
  • proxyRes: This event is emitted if the request to the target got a response.
  • open: This event is emitted once the proxy websocket was created and piped into the target websocket.
  • close: This event is emitted once the proxy websocket was closed.
  • (DEPRECATED) proxySocket: Deprecated in favor of open.
var httpProxy = require('http-proxy');
// Error example
//
// Http Proxy Server with bad target
//
var proxy = httpProxy.createServer({
  target:'http://localhost:9005'
});

proxy.listen(8005);

//
// Listen for the `error` event on `proxy`.
proxy.on('error', function (err, req, res) {
  res.writeHead(500, {
    'Content-Type': 'text/plain'
  });

  res.end('Something went wrong. And we are reporting a custom error message.');
});

//
// Listen for the `proxyRes` event on `proxy`.
//
proxy.on('proxyRes', function (proxyRes, req, res) {
  console.log('RAW Response from the target', JSON.stringify(proxyRes.headers, true, 2));
});

//
// Listen for the `open` event on `proxy`.
//
proxy.on('open', function (proxySocket) {
  // listen for messages coming FROM the target here
  proxySocket.on('data', hybiParseAndLogMessage);
});

//
// Listen for the `close` event on `proxy`.
//
proxy.on('close', function (res, socket, head) {
  // view disconnected websocket connections
  console.log('Client disconnected');
});

Back to top

Shutdown

  • When testing or running server within another program it may be necessary to close the proxy.
  • This will stop the proxy from accepting new connections.
var proxy = new httpProxy.createProxyServer({
  target: {
    host: 'localhost',
    port: 1337
  }
});

proxy.close();

Back to top

Miscellaneous

If you want to handle your own response after receiving the proxyRes, you can do so with selfHandleResponse. As you can see below, if you use this option, you are able to intercept and read the proxyRes but you must also make sure to reply to the res itself otherwise the original client will never receive any data.

Modify response

    var option = {
      target: target,
      selfHandleResponse : true
    };
    proxy.on('proxyRes', function (proxyRes, req, res) {
        var body = [];
        proxyRes.on('data', function (chunk) {
            body.push(chunk);
        });
        proxyRes.on('end', function () {
            body = Buffer.concat(body).toString();
            console.log("res from proxied server:", body);
            res.end("my response to cli");
        });
    });
    proxy.web(req, res, option);

ProxyTable API

A proxy table API is available through this add-on module, which lets you define a set of rules to translate matching routes to target routes that the reverse proxy will talk to.

Test

$ npm test

Logo

Logo created by Diego Pasquali

Back to top

Contributing and Issues

  • Read carefully our Code Of Conduct
  • Search on Google/Github
  • If you can't find anything, open an issue
  • If you feel comfortable about fixing the issue, fork the repo
  • Commit to your local branch (which must be different from master)
  • Submit your Pull Request (be sure to include tests and update documentation)

Back to top

License

The MIT License (MIT)

Copyright (c) 2010 - 2016 Charlie Robbins, Jarrett Cruger & the Contributors.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

node-http-proxy's People

Contributors

131 avatar 3rd-eden avatar arggu avatar ashubham avatar avianflu avatar benatkin avatar bmeck avatar coderarity avatar colinmollenhour avatar cronopio avatar dominictarr avatar donasaur avatar indexzero avatar indutny avatar isaacs avatar jcrugzz avatar jfhbrook avatar jleal52 avatar marak avatar matthauck avatar minrk avatar mmalecki avatar olauzon avatar otaviojr avatar philjackson avatar renovate[bot] avatar rush avatar srossross avatar subnetmarco avatar yawnt avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

node-http-proxy's Issues

EventEmitter memory leak on node v0.3.5, with possible fix

I created a very simple http-proxy instance for some testing: https://gist.github.com/790342

Running on node v0.3.5, this immediately returns the warning:

(node) warning: possible EventEmitter memory leak detected. 11 listeners added. Use emitter.setMaxListeners() to increase limit.
Trace
at Pool.<anonymous> (events.js:101:17)
at Object.proxyRequest (/usr/local/lib/node/.npm/http-proxy/0.3.1/package/lib/node-http-proxy.js:185:7)
at Server.<anonymous> (/usr/local/lib/node/.npm/http-proxy/0.3.1/package/lib/node-http-proxy.js:91:13)
at Server.emit (events.js:45:17)
at HTTPParser.onIncoming (http.js:862:12)
at HTTPParser.onHeadersComplete (http.js:85:31)
at Socket.ondata (http.js:787:22)
at Socket._onReadable (net.js:623:27)
at IOWatcher.onReadable [as callback] (net.js:156:10)

when an http request is made. Under load, it appears this is indeed leaking memory. After about 5 minutes with Siege hitting the proxy with 400 concurrent requests, it dies with:
FATAL ERROR: CALL_AND_RETRY_2 Allocation failed - process out of memory

However, removing the (empty?) pool error handler on line 184 of node-http-proxy.js appears to fix this. Should this be set once upon pool creation, rather than when the pool is retrieved for each request?

x-forwarded-for not set for https

(Reported by @bluescreen303)

I noticed x-forwarded-for was set to 'undefined' when proxying https.
It seems someone else was hit by this too.
http://stackoverflow.com/questions/5999379/how-to-find-out-the-remote-address-in-node-js-if-it-is-https-request

I'm not sure if this is a node bug, but as a workaround, would you please change

req.headers['x-forwarded-for'] = req.connection.remoteAddress;

into

req.headers['x-forwarded-for'] = req.connection.remoteAddress || req.connection.socket.remoteAddress;

Or maybe there's some other way around this problem.

Routing table unexpected behaviour

var httpProxy = require('http-proxy');
var options = {
router: {
'domain.com/path: '127.0.0.1:3000'
}
var proxyServer = httpProxy.createServer(options);
proxyServer.listen(80);

When now requesting domain.com/path in the browser, the answer is 127.0.0.1:3000/path but should be 127.0.0.1:3000/ instead

Version 0.5.0 returns "Invalid argument to getAgent" on examples

I'm new to http-proxy but after running the example here:

https://github.com/nodejitsu/node-http-proxy/blob/v0.5.0/examples/basic-proxy.js

With some modifications (changed path of http-proxy to work in my environment) it starts but immediately throws an exception when the first client tries to connect. Is there additional setup I need to do to get it running? I am running node v0.5.0-pre according to "node --version" and just pulled http-agent from npm today (2011, April 26th).

Here is the full exception:

http.js:1446
    throw new TypeError('Invalid argument to getAgent');
          ^
TypeError: Invalid argument to getAgent
    at Object.getAgent (http.js:1446:11)
    at _getAgent (/home/tim/local/node/lib/node/.npm/http-proxy/0.5.0/package/lib/node-http-proxy.js:48:30)
    at [object Object].proxyRequest (/home/tim/local/node/lib/node/.npm/http-proxy/0.5.0/package/lib/node-http-proxy.js:377:12)
    at Server. (/home/tim/local/node/lib/node/.npm/http-proxy/0.5.0/package/lib/node-http-proxy.js:146:13)
    at Server.emit (events.js:67:17)
    at HTTPParser.onIncoming (http.js:1109:12)
    at HTTPParser.onHeadersComplete (http.js:108:31)
    at Socket.ondata (http.js:1008:22)
    at Socket._onReadable (net.js:682:27)
    at IOWatcher.onReadable [as callback] (net.js:177:10)

Error during WebSocket handshake: origin mismatch

error in chrome:
Error during WebSocket handshake: origin mismatch : http://outside.host != http://localhost
the websocket reverse proxy doesn't seem to do its job completely.
It does proxy the handshake to the desired port and host (localhost), but the answer comes back with the back-end host instead of the origin.
In case of an extra proxy outside.host in front of the http-proxy, this makes the websocket connections fail
(unless a trick is applied with /etc/hosts to make to map outside.host to localhost).
http-proxy version 0.5.0, node version 0.4.6
Tested in chrome.

Cannot find module './lib/index'

Node 0.4.3
npm 1.0rc8
Ubuntu Server 10.04

When I try to run the binary, I get the following error:

$ sudo ./node_modules/http-proxy/bin/node-http-proxy --config=/node-proxy-conf.json --port=80

node.js:134
throw e; // process.nextTick error, or 'error' event on first tick
^
Error: Cannot find module './lib/index'
at Function._resolveFilename (module.js:320:11)
at Function._load (module.js:266:25)
at require (module.js:348:19)
at Object. (/home/mcurtis/node_modules/http-proxy/node_modules/winston/node_modules/riak-js/index.js:1:80)
at Module._compile (module.js:404:26)
at Object..js (module.js:410:10)
at Module.load (module.js:336:31)
at Function._load (module.js:297:12)
at require (module.js:348:19)
at Object. (/home/mcurtis/node_modules/http-proxy/node_modules/winston/lib/winston/transports/riak.js:10:14)

Any ideas? according to the riakjs issues list, there isn't an officially-compatible node 0.4 version of riakjs. I'm guessing that plus the new architecture of npm has something to do with this.

New experimental branch using net module

I'm not sure if this is the best place, but I wanted to get a dialog going regarding the new branch of http-proxy which is intended to use the net module.

I know that @ry and @mikeal both have a lot of thoughts about this, so if either of you guys feel like bike shedding, please post whatever information you can that could help direct @indexzero and @olauzon

:-)

Generalized (jsonp) proxy

One of the common issues these days is making requests to third part domains that don't support json and/or jsonp. Please provide an example of this in your demo.

I wrote one that kind of sucks here: https://gist.github.com/864549. 75% of the code is to prevent errors that would crash NodeJS.

For example,
/?url=http://www.google.com/calendar/feeds/[email protected]/public/full?alt=json
Or for XML, User needs to convert this to JSON
/?url=http://www.google.com/calendar/feeds/[email protected]/public/full

This sort of works, obviously its broken b/c I don't rebuild absolute URLs:
?url=http://google.com/

However, this one seriously breaks and I don't know why
?url=http://woot.com/

xhr-multipart forwarding

Just a minor nitpick
It seems xhr-multipart (keep-alive chunked) socket.io requests get dropped/killed by node-http-proxy.
Since there are enough other ways to connect, this is not a big issue, but I'm interested into why this happens.

I assume this piece of code is to "blame", but I couldn't find much info about keep-alive not being supported by node's http client.

// Force the connection header to be 'close' until
// node.js core re-implements 'keep-alive'.
outgoing.headers['connection'] = 'close';

So as stated, not a big issue, just would like to track this so I know when I can enable this transport again.

Faye problem

Hi, I'm using faye to broadcast realtime messages, but using node-http-proxy I receive this error:

/usr/local/lib/node/.npm/http-proxy/0.4.2/package/lib/node-http-proxy.js:439
  headers = new _headers(req.headers), CRLF = '\r\n';
                            ^
TypeError: Cannot read property 'headers' of undefined
  at [object Object].proxyWebSocketRequest (/usr/local/lib/node/.npm/http-proxy/0.4.2/package/lib/node-http-proxy.js:439:33)
  at Server.<anonymous> (/usr/local/lib/node/.npm/http-proxy/0.4.2/package/lib/node-http-proxy.js:142:13)
  at Server.emit (events.js:81:20)
  at Socket.<anonymous> (http.js:1023:14)
  at Socket._onReadable (net.js:677:27)
  at IOWatcher.onReadable [as callback] (net.js:177:10)

And in chrome console I see POST http://nodelytics.strx.int/faye undefined

My proxy configuration in simple

 var httpProxy = require('http-proxy');
 var options = {
  hostnameOnly:true,
  router: {
    'nodelytics.strx.int': '127.0.0.1:8001',
    'pagetitle.strx.int':  '127.0.0.1:8002',    
  }
};
var proxyServer = httpProxy.createServer(options), port=80;
proxyServer.listen(port);
log('HTTP Proxy Ready on port ', port, ', options: ', options);

I'm not sure, but seams to happen when client side code tries to connect to websocket

var client = new Faye.Client('/faye', {
  timeout: 120
});

Can you help me? Thanks

Changing the case of proxied headers breaks poorly written clients

I am working with a system that is very sensitive, against the standards, to the case of headers that are passed back to it. The current code in node-http-proxy takes all of the headers (ie. "Content-Type") and converts them to lower case. I know that the client is behaving badly here but it would be nice to have this configurable. I will see if I can code this up and send a pull request.

In the meantime, is there a way to disable this behavior?

allow ressource filters/callbacks

as discussed on twitter, it would be very interesting to be able to hack proxied ressources before sending them back to the client.

something like ressource filtering where we'll be able to change the response body/headers

wonder how to integrate this into node http proxy

Load balancer example (wishlist)

Hi Charlie,
I'm new to node.js (I learned of it... today), and your http-proxy is one of the first apps I found. The approach is new and very interesting.
However, from your explanation, it seems it can also be used as a kind of load balancer (I have 2 web servers, ws1 and ws2, and the http-proxy at hp1 could connect to both).

Is there an example about that? Maybe it's trivial and a I'm missing something. Or this use-case has to be developed from scratch?

Thank you
Paolo

https socket error (ECONNRESET, Connection reset by peer)

Hi, I come across this error when stress test node-http-proxy, using basic-proxy-https script.js

The test is based on a simple python script that use wget:

!/usr/local/bin/python

import os,signal,sys

count = 0
while(count < 1000):
os.system("wget --no-check-certificate --secure-protocol=SSLv3 --spider 'https://172.168.1\
.19:8081/'");

node proxy will run for a while then will shutdown with error:

net.js:825
close(this.fd);
^
Error: ECONNRESET, Connection reset by peer
at Socket.destroy (net.js:825:5)
at Socket._onReadable (net.js:652:30)
at IOWatcher.onReadable as callback

load balancing

But can you load balance the same hostheader name to different ports on different machines.
The Tables feature does not support this i think from reading of example.

Also would be create to support sticky and round robin patterns as default ones.
Round robin can use pinging to the web servers to determine the load and they can return a number between 1 and 100 to tell the load balancer their load indication.

https proxy: socket hang up

I'm getting this error when using https:

An error has occurred: {"stack":"Error: socket hang up\n at CleartextStream. (http.js:1272:45)\n at CleartextStream.emit (events.js:61:17)\n at Array.0 (tls.js:617:22)\n at EventEmitter._tickCallback (node.js:126:26)","message":"socket hang up"}

When running http it all works just fine.

Someone else has recently had a similar problem and was able to solve it (not sure if this would apply here though):

http://stackoverflow.com/questions/5680543/nodejs-https-request-for-oauth2-token-google-facebook-produce-error-socket-ha

Crash on request with bad headers?

Hmm,

This is a bit of an lousy bug report, more of an notion. I had the http-proxy module fail with the following error message:

/root/local/node/lib/node/.npm/http-proxy/0.3.1/package/lib/proxy-table.js:80
  var target = proxy.req.headers.host.split(':')[0] + proxy.req.url;
                                      ^
TypeError: Cannot call method 'split' of undefined
    at [object Object].proxyRequest (/root/local/node/lib/node/.npm/http-proxy/0.3.1/package/lib/proxy-table.js:80:39)
    at Server.<anonymous> (/root/local/node/lib/node/.npm/http-proxy/0.3.1/package/lib/node-http-proxy.js:93:18)
    at Server.emit (events.js:45:17)
    at HTTPParser.onIncoming (http.js:1078:12)
    at HTTPParser.onHeadersComplete (http.js:87:31)
    at Socket.ondata (http.js:977:22)
    at Socket._onReadable (net.js:654:27)
    at IOWatcher.onReadable [as callback] (net.js:156:10)

Was not able to identify what caused it.... trying reproduce. Any idea?

test suite fails w/ ECONNREFUSED

I'm running into issues that seem like a problem with just my system but I was hoping to find some assistance.

node 0.4.7
http-proxy 0.5.0
vows 0.5.8
colors 0.5.0
optimist 0.2.0
request 1.9.5
socket.io 0.6.17
on mac os x 10.6.7

When I run

 vows test/*-test.js --spec

all tests fail that are not expecting a 404 or 500.

The errors look like this:

When using server created by httpProxy.createServer() with no latency and a valid target server
✗ should receive 'hello localhost'
» expected 'hello localhost',
got  'An error has occurred: {"stack":"Error: ECONNREFUSED, Connection refused\\n    
at Socket._onConnect (net.js:599:18)\\n    at IOWatcher.onWritable [as callback 
(net.js:186:12)","message":"ECONNREFUSED, Connection      
refused","errno":61,"code":"ECONNREFUSED","syscall":"connect"}' (==) // helpers.js:77

Anyone seen this before? Seems like I'm missing something important. There is very little information on ECONNREFUSED. I do know that the error happens on making the request from proxy to target using the 'request' module (which is expected given the error) but I can't determine why. I'm hoping there's something simple I missed.

the example for routing websockets and normal http traffic fails

When I install http-proxy with npm, with node 0.4.2, and I run the example in the README doing a routing using server.on('upgrade', I get:
node.js:116
throw e; // process.nextTick error, or 'error' event on first tick
^
TypeError: Cannot read property 'headers' of undefined
at Object. (/usr/local/lib/node/.npm/http-proxy/0.3.1/package/lib/node-http-proxy.js:133:11)
at Object. (/Users/elise/Rails/MediaSquare/proxy.js:7:15)
at Module._compile (module.js:383:26)
at Object..js (module.js:389:10)
at Module.load (module.js:315:31)
at Function._load (module.js:276:12)
at Array. (module.js:402:10)
at EventEmitter._tickCallback (node.js:108:26)

It looks like using new httpProxy.HttpProxy() without parameters fails ...

Add `x-forwarded-proto` and `x-forwarded-port` to outgoing request headers.

(Reported by @bluescreen303)

While you are at it, can you please add the 'x-forwarded-proto' header as well (http, https).
In my case, I let the proxy do ssl, and use plain http backend servers.
This works very well, but my backend servers need to know what urls to generate for internal links.
This header does the trick. I'm not sure if it's standard in any way, but at least rails uses it.

Also, see https://forums.aws.amazon.com/ann.jspa?annID=805 for more information about these headers.

Potential bug using `Connection: close` header

Remark: Extrapolated from the nodejs-dev mailing list (thanks fidian)

I have updated the proxy code. Here's the newer invocation:

require('http-proxy').createServer(8002, 'localhost').listen(8001);

I have tried the following scenarios:

  • GET without Connection: close = success
  • GET with Connection: close = success
  • POST without Connection: close = success
  • POST with Connection: close = FAIL

I have a logging TCP proxy both on the incoming and outgoing sides of
this proxy to see what's sent and received. It is identical to what I
saw when my older code was using sys.puts(). I see that the server is
indeed sending a response and that the JS proxy is not relaying that
information to the client. The time stamps indicate that the
connection is actually closed before the connection to the destination
server is made. Incoming:

-------- CLIENT TO PROXY START --------
[00:00.000 - client 127.0.0.1:35062 forwarded to :8001]
POST /test.php?postclosed HTTP/1.1
Content-Type: application/x-www-form-urlencoded; charset=utf-8
Content-Length: 47
Connection: close
Host: censored.com

AUTHTOKEN=FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF

[00:00.001 - server connected]
[00:00.002 - server closed]
-------- CLIENT TO PROXY END --------

And here's what's logged on the other side:

-------- PROXY TO SERVER START --------
[00:00.000 - client 127.0.0.1:33945 forwarded to devweb1:81]
POST /test.php?postclosed HTTP/1.1
content-type: application/x-www-form-urlencoded; charset=utf-8
content-length: 47
connection: close
host: censored.com
x-forwarded-for: 127.0.0.1

AUTHTOKEN=FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF
[00:00.036 - server connected]
HTTP/1.1 200 OK
Date: Tue, 26 Apr 2011 16:35:00 GMT
Server: Apache/2.2.14 (Fedora)
X-Powered-By: PHP/5.3.3
Content-Length: 503
Connection: close
Content-Type: text/html; charset=UTF-8

{ ... hundreds of bytes of JSON data removed ... }
[00:00.079 - server closed]
-------- PROXY TO SERVER END --------

Host header and x-forwarded-for

Forgive me if this post is slightly uninformed - I am new to Proxying in general. Today I tried to start a proxy to get around some cross domain issues I was having. Apparently the urls I need to proxy to depend on the Host header being the same as the actual domain. When I was hitting it with node-http-proxy, I got some 403s, since it was sending Host : localhost (or whatever). It turns out my service doesn't honor the x-forwarded-for header and I have to fake it, but I'm surprised that this library doesn't automatically append the x-forwarded-for header to the request. From my general understanding it seems like most proxy systems do inject this header, so why doesn't node-http-proxy?

Changing headers should be an option

changing the headers "location" & "origin" when proxying websocket request should be an option, because this is important to make the proxying behave like "not happened".

failure with proxyRequest when using http-proxy and connect if bodyDecoder() installed in chain during a POST request

Hi there,

I've come across what I think is a bug (or at least an incompatibility) within http-proxy.

What I expect to happen: when I make a proxied POST request to the backend, it should process the request normally.

What happens instead: when I make a proxied POST request with the Connect.bodyDecoder() middleware installed, the request hangs forever in the proxy.

I created a very simple test case here: http://vivoh.com/node-proxy.zip

If you unzip this (and have ruby and the sinatra gem installed), you can see what I mean.

Run as is using the run.sh script, and then hit http://localhost:4568. Then, hit the "Submit Query" button. You'll see the http-proxy module successfully proxies the POST request request to the backend sinatra ruby server.

If you then edit "app.js" and uncomment the Connect.bodyDecoder() line, and then kill the node and ruby servers, and then restart using run.sh, if you try the POST request again, you'll see it hangs forever. I speculate there is something happening inside the bodyDecoder() middleware which is incompatible with the http-proxy module. I've looked around, but have not figured it out myself.

Chris

unusual behavior when proxying websocket to socket.io

I'm not really sure how to explain so
I whipped up some code to demonstrate.

https://gist.github.com/967964

please run that, then open 3 (console-supporting) browsers at http://localhost:8000
(i hope to find something to simulate in the future)
hit send in each
(you may need to modify node-http-proxy to not change headers)
console will log msgs rcvd from server.

then open 3 more browsers at http://localhost:9000 (no proxy)
hit send in each

notice the output is different.
also, the server output is different.

when proxied, messages are duplicated for client X depending on the number of clients connected after X.
also, connections disconnect after some time when proxied while they remain open indefinitely when not proxied.

node 0.4.7
npm 1.0.6
node-http-proxy 0.5.1
socket.io 0.6.17

How to find pool module?

Hi, I download node-http-proxy source package and put the node-http-proxy.js under $Node_Lib path. But I can't find the pool that required in node-http-proxy. So it throw the error. I also can't find this module in github.
Could u help me? Thanks in advanced.

Installation Error

I am trying to install node http-proxy with the following:

npm install http-proxy

But I get the following error:

npm ERR! Unsupported
npm ERR! Not compatible with your version of node/npm: [email protected]
npm ERR! Required: {"node":"= 0.4.7"}
npm ERR! Actual:   {"npm":"1.0.6","node":"v0.5.0-pre"}
npm ERR!
npm ERR! System Linux 2.6.18-028stab070.14
npm ERR! command "node" "/usr/local/bin/npm" "install" "http-proxy"

It says that it is unsupported with my version of Node. But I have v0.5.0 installed which is above the necessary v0.4.7.

Please advise.

proxy headers not added for websocket requests

I would like the proxy headers that are set for normal proxyd requests to appear on websocket requests as well.

  • x-forwarded-for
  • x-forwarded-port
  • x-forwarded-proto

Thanks a lot,
Mathijs

add back ability to proxy requests inside an existing httpServer for Connect support

was getting a couple of people in the IRC having issues with v0.2.0 of the proxy.

it seems when using the proxy inside of a Connect app, you really need the third API usage.

here is a gist with one of the example usages:
http://gist.github.com/571216

current workaround is to run:

 sudo npm install [email protected]

this will install http-proxy version 0.1.5, which has support proxying requests inside of an http.Server

How to do 301 Redirects

I'm trying to remove the www. requests to point them to the canonical non www. urls. This is the make sure copy pasted urls point to one domain and thus not divide up my Google Page Rank juice across the two domains.

gzip encoding

It would be awesome if node-http-proxy could gzip the responses so I could use it to add gzip capability do an "not-so-modern" backend server.

A way to add new routes?

Say I have a server at example.com and each time a user signs up I want to spin up a new node process that maps to username.example.com, is there an easy way to add this to the route list if I'm using hostname routing, or will I need to just use the custom logic mode?

I'm thinking it'd be handy to be able to do something like this;

var proxy = httpProxy.createServer(options);
proxy.addHost('username.example.com', '127.0.0.1:9000');

HTTP/1.0 proxied as HTTP/1.1

Sample code:

require('http-proxy').createServer(80, 'localhost').listen(8001); 

Sample request:

GET /phpinfo.php HTTP/1.0
Host: localhost:8001

Request that goes to the server:

GET /phpinfo.php HTTP/1.1
host: localhost:8001
x-forwarded-for: 127.0.0.1
x-forwarded-port: 38349
x-forwarded-proto: http
Connection: close

The server's response for this page looks like this:

HTTP/1.1 200 OK
Date: Thu, 09 Jun 2011 14:53:41 GMT
Server: Apache/2.2.17 (Ubuntu)
X-Powered-By: PHP/5.3.5-1ubuntu7.2
Vary: Accept-Encoding
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html

259f
<html><head>...lots of HTML

The response to the client looks identical. This, unfortunately, breaks the HTTP/1.0 response since now we are both sending an HTTP/1.1 status and we are doing chunked encoding. The HTTP/1.0 client can't understand this.

The fix: Make the request to the server an HTTP/1.0 request to mirror the client's desires perfectly.

argument parsing problem?

I just had this happen, dunno what to do. This could be a problem with optimist?

$ node-http-proxy --port 8000 --target localhost:8000 --target test.localhost:1234
The 'sys' module is now called 'util'. It should have a similar interface.

node.js:50
    throw e; // process.nextTick error, or 'error' event on first tick
    ^
TypeError: Object true,true has no method 'split'
    at Object. (/Users/david/local/lib/node/.npm/http-proxy/0.3.1/package/bin/node-http-proxy:52:31)
    at Module._compile (node.js:348:23)
    at Object..js (node.js:356:12)
    at Module.load (node.js:279:25)
    at loadModule (node.js:251:12)
    at require (node.js:291:14)
    at Object. (/Users/david/local/bin/node-http-proxy:11:18)
    at Module._compile (node.js:348:23)
    at Object..js (node.js:356:12)
    at Module.load (node.js:279:25)

Add support for host name based proxying

I want to proxy out multiple web servers running on a single ip address with different host names. I need to be able to listen to port 80 and, depending on the domain name, serve up the respective website.

WebSocket support

Is node-http-proxy supposed to support websockets? It seems that websocket are not passed through (according to my testing), is that correct or do I have to configure something differently?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.