Permalink
Browse files

[api] merge middleware branch

  • Loading branch information...
2 parents 5ba0f89 + 0f8fe8e commit e6ff8d6597a977baf0caf4f69c75bfa93d7281f3 @dominictarr dominictarr committed Aug 2, 2011
View
@@ -43,6 +43,7 @@ There are several ways to use node-http-proxy; the library is designed to be fle
3. In conjunction with a Proxy Routing Table
4. As a forward-proxy with a reverse proxy
5. From the command-line as a long running process
+6. customized with 3rd party middleware.
In each of these scenarios node-http-proxy can handle any of these types of requests:
@@ -312,6 +313,16 @@ https.createServer(options.https, function (req, res) {
res.end();
}).listen(8000);
```
+## Middleware
+
+`node-http-proxy` now supports connect middleware. Add middleware functions to your createServer call:
+
+``` js
+httpProxy.createServer(
+ require('connect-gzip').gzip(),
+ 9000, 'localhost'
+).listen(8000);
+```
## Proxying WebSockets
Websockets are handled automatically when using the `httpProxy.createServer()`, but if you want to use it in conjunction with a stand-alone HTTP + WebSocket (such as [socket.io][5]) server here's how:
View
@@ -0,0 +1,72 @@
+/*
+ body-decoder.js: Example of body-decoder middleware with node-http-proxy
+
+ Copyright (c) 2010 Charlie Robbins, Mikeal Rogers, Fedor Indutny, & Marak Squires.
+
+ 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.
+
+*/
+
+var httpProxy = require('http-proxy'),
+ http = require('http'),
+ util = require('util'),
+ colors = require('colors');
+
+exports.bodyMod = function () {
+ console.log('middleware has been started.'.green);
+ return function (req, res, next) {
+ var proxy = next,
+ total = '';
+
+ req.on('data', function (data) {
+ console.log('ON DATA')
+ total += data;
+ });
+
+ req.on('end', function () {
+ console.log('ON END')
+ console.log(total);
+ //
+ // This line, uncommented, hangs forever.
+ // proxy.proxyRequest(req, res, { port: 9000, host: 'localhost' });
+ // The following also hangs forever.
+ // next.proxyRequest(req, res, { port: 9000, host: 'localhost' });
+ //
+ });
+
+ //
+ // The following fires just fine.
+ //proxy.proxyRequest(req, res, { port: 9000, host: 'localhost' });
+ //
+ console.log('request proxied...'.blue);
+ }
+}
+
+var proxyServer = httpProxy.createServer(
+ // Your middleware stack goes here.
+ exports.bodyMod()
+).listen(8000);
+
+
+var httpServer = 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(9000);
@@ -0,0 +1,87 @@
+
+var Store = require('./lib/store')
+ , http = require('http')
+
+http.createServer(new Store().handler()).listen(7531, function () {
+//try these commands:
+// get index:
+// curl localhost:7531
+// []
+//
+// get a doc:
+// curl localhost:7531/foo
+// {"error":"not_found"}
+//
+// post an doc:
+// curl -X POST localhost:7531/foo -d '{"content": "hello", "type": "greeting"}'
+// {"ok":true}
+//
+// get index (now, not empty)
+// curl localhost:7531
+// ["/foo"]
+//
+// get doc
+// curl localhost:7531/foo
+// {"content": "hello", "type": "greeting"}
+
+//
+// now, suppose we wanted to direct all objects where type == "greeting" to a different store
+// than where type == "insult"
+//
+// we can use connect connect-bodyDecoder and some custom logic to send insults to another Store.
+
+//insult server:
+
+ http.createServer(new Store().handler()).listen(2600, function () {
+
+ //greetings -> 7531, insults-> 2600
+
+ // now, start a proxy server.
+
+ var bodyParser = require('connect/lib/middleware/bodyParser')
+ //don't worry about incoming contont type
+ //bodyParser.parse[''] = JSON.parse
+
+ require('http-proxy').createServer(
+ //refactor the body parser and re-streamer into a separate package
+ bodyParser(),
+ //body parser absorbs the data and end events before passing control to the next
+ // middleware. if we want to proxy it, we'll need to re-emit these events after
+ //passing control to the middleware.
+ require('connect-restreamer')(),
+ function (req, res, proxy) {
+ //if your posting an obect which contains type: "insult"
+ //it will get redirected to port 2600.
+ //normal get requests will go to 7531 nad will not return insults.
+ var port = (req.body && req.body.type === 'insult' ? 2600 : 7531)
+ proxy.proxyRequest(req, res, {host: 'localhost', port: port})
+ }
+ ).listen(1337, function () {
+ var request = require('request')
+ //bodyParser needs content-type set to application/json
+ //if we use request, it will set automatically if we use the 'json:' field.
+ function post (greeting, type) {
+ request.post({
+ url: 'http://localhost:1337/' + greeting,
+ json: {content: greeting, type: type || "greeting"}
+ })
+ }
+ post("hello")
+ post("g'day")
+ post("kiora")
+ post("houdy")
+ post("java", "insult")
+
+ //now, the insult should have been proxied to 2600
+
+ //curl localhost:2600
+ //["/java"]
+
+ //but the greetings will be sent to 7531
+
+ //curl localhost:7531
+ //["/hello","/g%27day","/kiora","/houdy"]
+
+ })
+ })
+})
@@ -0,0 +1,65 @@
+/*
+ concurrent-proxy.js: check levelof concurrency through proxy.
+
+ Copyright (c) 2010 Charlie Robbins, Mikeal Rogers, Fedor Indutny, & Marak Squires.
+
+ 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.
+
+*/
+
+var util = require('util'),
+ colors = require('colors'),
+ http = require('http'),
+ httpProxy = require('./../lib/node-http-proxy');
+
+//
+// Basic Http Proxy Server
+//
+httpProxy.createServer(9000, 'localhost').listen(8000);
+
+//
+// Target Http Server
+//
+// to check apparent problems with concurrent connections
+// make a server which only responds when there is a given nubmer on connections
+//
+
+
+var connections = []
+ , go
+
+http.createServer(function (req, res) {
+
+ connections.push (function (){
+ res.writeHead(200, { 'Content-Type': 'text/plain' });
+ res.write('request successfully proxied to: ' + req.url + '\n' + JSON.stringify(req.headers, true, 2));
+ res.end();
+ })
+ process.stdout.write(connections.length + ', ')
+ if (connections.length > 110 || go) {
+ go = true
+ while(connections.length)
+ connections.shift()()
+ }
+
+}).listen(9000);
+
+util.puts('http proxy server'.blue + ' started '.green.bold + 'on port '.blue + '8000'.yellow);
+util.puts('http server '.blue + 'started '.green.bold + 'on port '.blue + '9000 '.yellow);
@@ -0,0 +1,50 @@
+/*
+ gzip-middleware.js: Basic example of `connect-gzip` middleware in node-http-proxy
+
+ Copyright (c) 2010 Charlie Robbins, Mikeal Rogers, Fedor Indutny, Marak Squires, & Dominic Tarr.
+
+ 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.
+
+*/
+
+var util = require('util'),
+ colors = require('colors'),
+ http = require('http'),
+ httpProxy = require('./../lib/node-http-proxy');
+
+//
+// Basic Http Proxy Server
+//
+httpProxy.createServer(
+ require('connect-gzip').gzip({ matchType: /.?/ }),
+ 9000, 'localhost'
+).listen(8000);
+
+//
+// Target Http 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(9000);
+
+util.puts('http proxy server'.blue + ' started '.green.bold + 'on port '.blue + '8000'.yellow);
+util.puts('http server '.blue + 'started '.green.bold + 'on port '.blue + '9000 '.yellow);
@@ -0,0 +1,30 @@
+var Store = require('./lib/store')
+ , http = require('http')
+
+//
+// jsonp is a handy technique for getting around the limitations of the same-origin policy.
+// (http://en.wikipedia.org/wiki/Same_origin_policy)
+//
+// normally, to dynamically update a page you use an XmlHttpRequest. this has flakey support
+// is some browsers and is restricted by the same origin policy. you cannot perform XHR requests to
+// someone else's server. one way around this would be to proxy requests to all the servers you want
+// to xhr to, and your core server - so that everything has the same port and host.
+//
+// another way, is to turn json into javascript. (which is exempt from the same origin policy)
+// this is done by wrapping the json object in a function call, and then including a script tag.
+//
+// here we're proxing our own JSON returning server, but we could proxy any server on the internet,
+// and our client side app would be slurping down JSONP from anywhere.
+//
+// curl localhost:1337/whatever?callback=alert
+// alert([]) //which is valid javascript!
+//
+// also see http://en.wikipedia.org/wiki/JSONP#JSONP
+//
+
+http.createServer(new Store().handler()).listen(7531)
+
+require('http-proxy').createServer(
+ require('connect-jsonp')(true),
+ 'localhost', 7531
+).listen(1337)
Oops, something went wrong.

0 comments on commit e6ff8d6

Please sign in to comment.