-
Notifications
You must be signed in to change notification settings - Fork 2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[docs] add middleware examples (first draft)
- Loading branch information
1 parent
f7452bc
commit 020290a
Showing
3 changed files
with
215 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
|
||
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. | ||
function (req, res, next) { | ||
//remove bodyParser's listeners | ||
req.removeAllListeners('data') | ||
req.removeAllListeners('end') | ||
next() | ||
process.nextTick(function () { | ||
if(req.body) | ||
req.emit('data', JSON.stringify(req.body)) | ||
req.emit('end') | ||
}) | ||
}, | ||
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"] | ||
|
||
}) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
var util = require('util'), | ||
colors = require('colors'), | ||
http = require('http'), | ||
httpProxy = require('http-proxy'), | ||
Store = require('./lib/store') | ||
// | ||
// This is an example of a url-routing middleware. | ||
// This is not intended for production use, but rather as | ||
// an example of how to write a middleware. | ||
// | ||
|
||
function matcher (url, dest) { | ||
// First, turn the URL into a regex. | ||
// NOTE: Turning user input directly into a Regular Expression is NOT SAFE. | ||
var r = new RegExp(url.replace(/\//, '\\/')); | ||
// This next block of code may look a little confusing. | ||
// It returns a closure (anonymous function) for each URL to be matched, | ||
// storing them in an array - on each request, if the URL matches one that has | ||
// a function stored for it, the function will be called. | ||
return function (url) { | ||
var m = r(url) | ||
if (!m) { | ||
return; | ||
} | ||
var path = url.slice(m[0].length); | ||
console.log('proxy:', url, '->', dest); | ||
return {url: path, dest: dest}; | ||
} | ||
} | ||
|
||
exports.urls = function (urls) { | ||
// This is the entry point for our middleware. | ||
// 'matchers' is the array of URL matchers, as mentioned above. | ||
var matchers = []; | ||
for (var url in urls) { | ||
// Call the 'matcher' function above, and store the resulting closure. | ||
matchers.push(matcher(url, urls[url])); | ||
} | ||
|
||
// This closure is returned as the request handler. | ||
return function (req, res, next) { | ||
// | ||
// in node-http-proxy middlewares, `proxy` is the prototype of `next` | ||
// (this means node-http-proxy middlewares support both the connect API (req, res, next) | ||
// and the node-http-proxy API (req, res, proxy) | ||
// | ||
var proxy = next; | ||
for (var k in matchers) { | ||
// for each URL matcher, try the request's URL. | ||
var m = matchers[k](req.url); | ||
// If it's a match: | ||
if (m) { | ||
// Replace the local URL with the destination URL. | ||
req.url = m.url; | ||
// If routing to a server on another domain, the hostname in the request must be changed. | ||
req.headers.host = m.host; | ||
// Once any changes are taken care of, this line makes the magic happen. | ||
proxy.proxyRequest(req, res, m.dest); | ||
} | ||
} | ||
} | ||
} | ||
|
||
http.createServer(new Store().handler()).listen(7531) | ||
|
||
// Now we set up our proxy. | ||
httpProxy.createServer( | ||
// This is where our middlewares go, with any options desired - in this case, | ||
// the list of routes/URLs and their destinations. | ||
exports.urls({ | ||
'/store': { port: 7531, host: 'localhost' }, | ||
'/': { port: 9000, host: 'localhost' } | ||
}) | ||
).listen(8000); | ||
|
||
// | ||
// Target Http Server (to listen for requests on 'localhost') | ||
// | ||
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); | ||
|
||
// And finally, some colored startup output. | ||
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); |