Permalink
Browse files

cleaning up http-server interface.

  • Loading branch information...
1 parent 4f98049 commit 155c9cda753dca86cb65c3b418686b2148e1c72b @satyamshekhar satyamshekhar committed Apr 26, 2012
Showing with 396 additions and 402 deletions.
  1. +1 −1 run-server.js
  2. +15 −64 src/bosh.js
  3. +7 −0 src/cross-domain.xml
  4. +0 −48 src/helper.js
  5. +23 −0 src/http-headers.js
  6. +219 −0 src/http-request-handler.js
  7. +0 −226 src/http-server.js
  8. +36 −5 src/main.js
  9. +0 −30 src/options.js
  10. +73 −22 src/response.js
  11. +17 −0 src/stats.xml
  12. +5 −6 src/websocket.js
View
@@ -170,7 +170,7 @@ function main() {
new Date())
);
- var ws_server = nxb.start_websocket(bosh_server);
+ var ws_server = nxb.start_websocket(server_options);
}
// Go!!
View
@@ -32,7 +32,7 @@ var helper = require('./helper.js');
var opt = require('./options.js');
var path = require('path');
var bee = require('./bosh-event-emitter.js');
-var http = require('./http-server.js');
+var RequestHandler = require('./http-request-handler.js').RequestHandler;
var toNumber = us.toNumber;
var sprintf = dutil.sprintf;
@@ -70,7 +70,7 @@ var log = require('./log.js').getLogger(filename);
//
-exports.createServer = function (options) {
+exports.createServer = function (options, http_server) {
//
// +-------+
// | NOTE: |
@@ -82,44 +82,10 @@ exports.createServer = function (options) {
// (and only) place of reference for object structure.
//
- var started;
var session_store;
var stream_store;
var bep;
var bosh_options;
- var server;
-
- started = new Date(); // When was this server started?
-
- function get_statistics() {
- var stats = [ ];
- stats.push('<?xml version="1.0" encoding="utf-8"?>');
- stats.push('<!DOCTYPE html>');
- var content = new ltx.Element('html', {
- 'xmlns': 'http://www.w3.org/1999/xhtml',
- 'xml:lang': 'en'
- })
- .c('head')
- .c('title').t('node-xmpp-bosh').up()
- .up()
- .c('body')
- .c('h1')
- .c('a', {'href': 'https://github.com/dhruvbird/node-xmpp-bosh'})
- .t('node-xmpp-bosh')
- .up()
- .up()
- .c('h3').t('Bidirectional-streams Over Synchronous HTTP').up()
- .c('p').t(sprintf('Uptime: %s', dutil.time_diff(started, new Date()))).up()
- .c('p').t(sprintf('%s/%s active %s', session_store.get_active_no(),
- session_store.get_total_no(),
- dutil.pluralize(session_store.get_total_no(), 'session'))).up()
- .c('p').t(sprintf('%s/%s active %s', stream_store.get_active_no(),
- stream_store.get_total_no(),
- dutil.pluralize(stream_store.get_total_no(), 'stream'))).up()
- .tree();
- stats.push(content.toString());
- return stats.join('\n');
- }
function process_bosh_request(res, node) {
// This will eventually contain all the nodes to be processed.
@@ -129,7 +95,6 @@ exports.createServer = function (options) {
var stream = null;
node = helper.sanitize_request_node(node);
-
// Check if this is a session start packet.
if (helper.is_session_creation_packet(node)) {
log.trace("Session Creation");
@@ -199,28 +164,6 @@ exports.createServer = function (options) {
}
- function http_error_handler(ex) {
- // We enforce similar semantics as the rest of the node.js for the 'error'
- // event and throw an exception if it is unhandled
- if (!bep.emit('error', ex)) {
- throw new Error(
- sprintf('ERROR on listener at endpoint: http://%s:%s%s',
- options.host, options.port, options.path)
- );
- }
- }
-
- //Called when the 'end' event for the request is fired by the HTTP request handler
- function bosh_request_handler(res, node) {
- if (!node) {
- res.writeHead(200, bosh_options.HTTP_POST_RESPONSE_HEADERS);
- res.end(helper.$terminate({ condition: 'bad-request' }).toString());
- return;
- }
- log.trace("Processing Request");
- process_bosh_request(res, node);
- }
-
// When the Connector is able to add the stream, we too do the same and
// respond to the client accordingly.
function _on_stream_added(stream) {
@@ -268,15 +211,20 @@ exports.createServer = function (options) {
session.terminate(condition);
}
}
-
+
bosh_options = new opt.BOSH_Options(options);
- server = new http.HTTPServer(options.port, options.host, get_statistics,
- bosh_request_handler, http_error_handler, bosh_options);
+
+ var request_handler = new RequestHandler({
+ host: options.host,
+ port: options.port,
+ path: options.path,
+ MAX_DATA_HELD: bosh_options.max_data_held || 100000
+ }, process_bosh_request);
+
// The BOSH event emitter. People outside will subscribe to
// events from this guy. We return an instance of BoshEventPipe
// to the outside world when anyone calls createServer()
- bep = new bee.BoshEventPipe(server.http_server);
-
+ bep = new bee.BoshEventPipe();
bep.on('stream-added', _on_stream_added);
bep.on('response', _on_response);
bep.on('terminate', _on_terminate);
@@ -286,5 +234,8 @@ exports.createServer = function (options) {
bep.set_session_data(session_store);
bep.set_stream_data(stream_store);
+
+ request_handler.start(http_server);
+
return bep;
};
View
@@ -0,0 +1,7 @@
+<?xml version="1.0"?>
+<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
+<cross-domain-policy>
+<site-control permitted-cross-domain-policies="all"/>
+<allow-access-from domain="*" to-ports="<%= port %>" secure="true"/>
+<allow-http-request-headers-from domain="*" headers="*" />'
+</cross-domain-policy>
View
@@ -68,53 +68,6 @@ function add_to_headers(dest, src) {
dest['Access-Control-Allow-Headers'] = acah.join(', ');
}
-function JSONPResponseProxy(req, res) {
- this.req_ = req;
- this.res_ = res;
- this.wrote_ = false;
-
- var _url = url.parse(req.url, true);
- this.jsonp_cb_ = _url.query.callback || '';
- // console.log("DATA:", _url.query.data);
- // console.log("JSONP CB:", this.jsonp_cb_);
-
- // The proxy is used only if this is a JSONP response
- if (!this.jsonp_cb_) {
- return res;
- }
-}
-
-JSONPResponseProxy.prototype = {
- on: function () {
- return this.res_.on.apply(this.res_, arguments);
- },
- writeHead: function (status_code, headers) {
- var _headers = { };
- dutil.copy(_headers, headers);
- _headers['Content-Type'] = 'application/json; charset=utf-8';
- return this.res_.writeHead(status_code, _headers);
- },
- write: function (data) {
- if (!this.wrote_) {
- this.res_.write(this.jsonp_cb_ + '({"reply":"');
- this.wrote_ = true;
- }
-
- data = data || '';
- data = data.replace(/\n/g, '\\n').replace(/"/g, '\\"');
- return this.res_.write(data);
- },
- end: function (data) {
- this.write(data);
- if (this.jsonp_cb_) {
- this.res_.write('"});');
- }
- return this.res_.end();
- },
- setHeader: function(name, value) {
- return this.res_.setHeader(name, value);
- }
-};
// End HTTP header helpers
// Begin misc. helpers
@@ -203,7 +156,6 @@ function is_session_creation_packet(node) {
// End misc. helpers
exports.add_to_headers = add_to_headers;
-exports.JSONPResponseProxy = JSONPResponseProxy;
exports.route_parse = route_parse;
exports.save_terminate_condition_for_wait_time = save_terminate_condition_for_wait_time;
exports.$terminate = $terminate;
View
@@ -0,0 +1,23 @@
+exports.GET = {
@dhruvbird

dhruvbird Apr 26, 2012

Owner

This is definitely cleaner.

@satyamshekhar

satyamshekhar Apr 26, 2012

Collaborator

The only problem with this, right now you can include custom headers. Will think of a way to do that.

@satyamshekhar

satyamshekhar Apr 26, 2012

Collaborator

*can't

+ 'Content-Type': 'application/xhtml+xml; charset=UTF-8',
+ 'Cache-Control': 'no-cache, no-store',
+ 'Access-Control-Allow-Origin': '*',
+ 'Access-Control-Allow-Headers': 'Content-Type, x-requested-with, Set-Cookie',
+ 'Access-Control-Allow-Methods': 'OPTIONS, GET, POST',
+ 'Access-Control-Max-Age': '14400'
+};
+
+exports.POST = {
+ 'Content-Type': 'text/xml; charset=UTF-8',
+ 'Access-Control-Allow-Origin': '*',
+ 'Access-Control-Allow-Headers': 'Content-Type, x-requested-with, Set-Cookie',
+ 'Access-Control-Allow-Methods': 'OPTIONS, GET, POST',
+ 'Access-Control-Max-Age': '14400'
+};
+
+exports.OPTIONS = {
+ 'Access-Control-Allow-Origin': '*',
+ 'Access-Control-Allow-Headers': 'Content-Type, x-requested-with, Set-Cookie',
+ 'Access-Control-Allow-Methods': 'POST, GET, OPTIONS',
+ 'Access-Control-Max-Age': '14400'
+};
Oops, something went wrong.

9 comments on commit 155c9cd

Owner

dhruvbird replied Apr 26, 2012

This won't work since websocket fails.

Collaborator

satyamshekhar replied Apr 26, 2012

Its not done yet. Will make it work.

Basically, I couldn't think of a reason to pass bep to websocket.

Collaborator

satyamshekhar replied Apr 26, 2012

Why do you say it wont work though?

Owner

dhruvbird replied Apr 26, 2012

Stats need updating. There is just 1 unified URL for session/stream stats.

Collaborator

satyamshekhar replied Apr 26, 2012

yup I was thinking of doing this differently. Basically take out session/stream store from session/stream and expose a method to count number of alive/total streams, assuming websockets would store their sessions there as well (which sounded reasonable - unless I missed something).

Owner

dhruvbird replied Apr 26, 2012

What does this achieve? Rather what is the motivation behind it?

Does it simplify anything? Make any currently un-implementable (or hard to implement feature) possible (or easier)? Does it fix any bugs?

Related question: What do you think is grossly wrong with the current scheme of things?

Collaborator

satyamshekhar replied Apr 26, 2012

What does this achieve? Rather what is the motivation behind it?

While doing this, my main concern was fixing leaky interfaces - and make it more readable/intutive.

Does it simplify anything? Make any currently un-implementable (or hard to implement feature) possible (or easier)? Does it fix any bugs?

Everything works right now, no doubt, but there is a lot of cohesion/leak - for example, websocket needing bep. Now, the next could be I can easily right tests for http-request handler. If we can get the code to a point where each module can be easily tested that would be pretty awsome.

Owner

dhruvbird replied Apr 26, 2012

Motivation is spot on. Let's discuss the best way to do this.
But before that, I think we should do a performance pass. There have been too many refactoring and cleanup passes which has probably affected performance.

Collaborator

satyamshekhar replied Apr 26, 2012

But before that, I think we should do a performance pass. There have been too many refactoring and cleanup passes which has probably affected performance.

This is the primary reason why I started this - so that I can benchmark each smaller unit more easily.
Things look pretty cool with node v0.6.15, though. Haven't seen any cpu spikes as such.

Please sign in to comment.