Skip to content

Commit 020290a

Browse files
committed
[docs] add middleware examples (first draft)
1 parent f7452bc commit 020290a

File tree

3 files changed

+215
-0
lines changed

3 files changed

+215
-0
lines changed

Diff for: examples/bodyDecoder-middleware.js

+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
2+
var Store = require('./lib/store')
3+
, http = require('http')
4+
5+
http.createServer(new Store().handler()).listen(7531, function () {
6+
//try these commands:
7+
// get index:
8+
// curl localhost:7531
9+
// []
10+
//
11+
// get a doc:
12+
// curl localhost:7531/foo
13+
// {"error":"not_found"}
14+
//
15+
// post an doc:
16+
// curl -X POST localhost:7531/foo -d '{"content": "hello", "type": "greeting"}'
17+
// {"ok":true}
18+
//
19+
// get index (now, not empty)
20+
// curl localhost:7531
21+
// ["/foo"]
22+
//
23+
// get doc
24+
// curl localhost:7531/foo
25+
// {"content": "hello", "type": "greeting"}
26+
27+
//
28+
// now, suppose we wanted to direct all objects where type == "greeting" to a different store
29+
// than where type == "insult"
30+
//
31+
// we can use connect connect-bodyDecoder and some custom logic to send insults to another Store.
32+
33+
//insult server:
34+
35+
http.createServer(new Store().handler()).listen(2600, function () {
36+
37+
//greetings -> 7531, insults-> 2600
38+
39+
// now, start a proxy server.
40+
41+
var bodyParser = require('connect/lib/middleware/bodyParser')
42+
//don't worry about incoming contont type
43+
//bodyParser.parse[''] = JSON.parse
44+
45+
require('http-proxy').createServer(
46+
//refactor the body parser and re-streamer into a separate package
47+
bodyParser(),
48+
//body parser absorbs the data and end events before passing control to the next
49+
// middleware. if we want to proxy it, we'll need to re-emit these events after
50+
//passing control to the middleware.
51+
function (req, res, next) {
52+
//remove bodyParser's listeners
53+
req.removeAllListeners('data')
54+
req.removeAllListeners('end')
55+
next()
56+
process.nextTick(function () {
57+
if(req.body)
58+
req.emit('data', JSON.stringify(req.body))
59+
req.emit('end')
60+
})
61+
},
62+
function (req, res, proxy) {
63+
//if your posting an obect which contains type: "insult"
64+
//it will get redirected to port 2600.
65+
//normal get requests will go to 7531 nad will not return insults.
66+
var port = (req.body && req.body.type === 'insult' ? 2600 : 7531)
67+
proxy.proxyRequest(req, res, {host: 'localhost', port: port})
68+
}
69+
).listen(1337, function () {
70+
var request = require('request')
71+
//bodyParser needs content-type set to application/json
72+
//if we use request, it will set automatically if we use the 'json:' field.
73+
function post (greeting, type) {
74+
request.post({
75+
url: 'http://localhost:1337/' + greeting,
76+
json: {content: greeting, type: type || "greeting"}
77+
})
78+
}
79+
post("hello")
80+
post("g'day")
81+
post("kiora")
82+
post("houdy")
83+
post("java", "insult")
84+
85+
//now, the insult should have been proxied to 2600
86+
87+
//curl localhost:2600
88+
//["/java"]
89+
90+
//but the greetings will be sent to 7531
91+
92+
//curl localhost:7531
93+
//["/hello","/g%27day","/kiora","/houdy"]
94+
95+
})
96+
})
97+
})

Diff for: examples/jsonp-middleware.js

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
var Store = require('./lib/store')
2+
, http = require('http')
3+
4+
//
5+
// jsonp is a handy technique for getting around the limitations of the same-origin policy.
6+
// (http://en.wikipedia.org/wiki/Same_origin_policy)
7+
//
8+
// normally, to dynamically update a page you use an XmlHttpRequest. this has flakey support
9+
// is some browsers and is restricted by the same origin policy. you cannot perform XHR requests to
10+
// someone else's server. one way around this would be to proxy requests to all the servers you want
11+
// to xhr to, and your core server - so that everything has the same port and host.
12+
//
13+
// another way, is to turn json into javascript. (which is exempt from the same origin policy)
14+
// this is done by wrapping the json object in a function call, and then including a script tag.
15+
//
16+
// here we're proxing our own JSON returning server, but we could proxy any server on the internet,
17+
// and our client side app would be slurping down JSONP from anywhere.
18+
//
19+
// curl localhost:1337/whatever?callback=alert
20+
// alert([]) //which is valid javascript!
21+
//
22+
// also see http://en.wikipedia.org/wiki/JSONP#JSONP
23+
//
24+
25+
http.createServer(new Store().handler()).listen(7531)
26+
27+
require('http-proxy').createServer(
28+
require('connect-jsonp')(true),
29+
'localhost', 7531
30+
).listen(1337)

Diff for: examples/url-middleware2.js

+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
var util = require('util'),
2+
colors = require('colors'),
3+
http = require('http'),
4+
httpProxy = require('http-proxy'),
5+
Store = require('./lib/store')
6+
//
7+
// This is an example of a url-routing middleware.
8+
// This is not intended for production use, but rather as
9+
// an example of how to write a middleware.
10+
//
11+
12+
function matcher (url, dest) {
13+
// First, turn the URL into a regex.
14+
// NOTE: Turning user input directly into a Regular Expression is NOT SAFE.
15+
var r = new RegExp(url.replace(/\//, '\\/'));
16+
// This next block of code may look a little confusing.
17+
// It returns a closure (anonymous function) for each URL to be matched,
18+
// storing them in an array - on each request, if the URL matches one that has
19+
// a function stored for it, the function will be called.
20+
return function (url) {
21+
var m = r(url)
22+
if (!m) {
23+
return;
24+
}
25+
var path = url.slice(m[0].length);
26+
console.log('proxy:', url, '->', dest);
27+
return {url: path, dest: dest};
28+
}
29+
}
30+
31+
exports.urls = function (urls) {
32+
// This is the entry point for our middleware.
33+
// 'matchers' is the array of URL matchers, as mentioned above.
34+
var matchers = [];
35+
for (var url in urls) {
36+
// Call the 'matcher' function above, and store the resulting closure.
37+
matchers.push(matcher(url, urls[url]));
38+
}
39+
40+
// This closure is returned as the request handler.
41+
return function (req, res, next) {
42+
//
43+
// in node-http-proxy middlewares, `proxy` is the prototype of `next`
44+
// (this means node-http-proxy middlewares support both the connect API (req, res, next)
45+
// and the node-http-proxy API (req, res, proxy)
46+
//
47+
var proxy = next;
48+
for (var k in matchers) {
49+
// for each URL matcher, try the request's URL.
50+
var m = matchers[k](req.url);
51+
// If it's a match:
52+
if (m) {
53+
// Replace the local URL with the destination URL.
54+
req.url = m.url;
55+
// If routing to a server on another domain, the hostname in the request must be changed.
56+
req.headers.host = m.host;
57+
// Once any changes are taken care of, this line makes the magic happen.
58+
proxy.proxyRequest(req, res, m.dest);
59+
}
60+
}
61+
}
62+
}
63+
64+
http.createServer(new Store().handler()).listen(7531)
65+
66+
// Now we set up our proxy.
67+
httpProxy.createServer(
68+
// This is where our middlewares go, with any options desired - in this case,
69+
// the list of routes/URLs and their destinations.
70+
exports.urls({
71+
'/store': { port: 7531, host: 'localhost' },
72+
'/': { port: 9000, host: 'localhost' }
73+
})
74+
).listen(8000);
75+
76+
//
77+
// Target Http Server (to listen for requests on 'localhost')
78+
//
79+
http.createServer(
80+
function (req, res) {
81+
res.writeHead(200, { 'Content-Type': 'text/plain' });
82+
res.write('request successfully proxied to: ' + req.url + '\n' + JSON.stringify(req.headers, true, 2));
83+
res.end();
84+
}).listen(9000);
85+
86+
// And finally, some colored startup output.
87+
util.puts('http proxy server'.blue + ' started '.green.bold + 'on port '.blue + '8000'.yellow);
88+
util.puts('http server '.blue + 'started '.green.bold + 'on port '.blue + '9000 '.yellow);

0 commit comments

Comments
 (0)