Skip to content

Commit

Permalink
Made req and res EventEmitters, added res 'final' event, added req.ip
Browse files Browse the repository at this point in the history
  • Loading branch information
elliothatch committed May 9, 2016
1 parent 2d02512 commit 751ec21
Show file tree
Hide file tree
Showing 8 changed files with 141 additions and 63 deletions.
9 changes: 5 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
language: node_js
node_js:
- node
- '0.12'
- '0.11'
- '0.10'
- node
- '5'
- '4'
- '0.12'
- '0.11'
before_install: npm install -g grunt-cli
after_success: npm run coveralls
deploy:
Expand Down
4 changes: 4 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## 0.1

### 0.1.2 - 5-8-16
- Made request and response objects inherit from EventEmitter. Response emits 'final' event when res.send is called.
- Added req.ip

### 0.1.1 - 5-2-16
- No longer crashes if recieved message is not an object
- Added support for query strings. Query strings don't affect the URL that responses are emitted to.
Expand Down
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,9 @@ The headers value from req.message. Use req.get() to retrieve header values.
### req.body
The body of the request, from req.body.

### req.ip
IP address of the client socket.

### req.res
Handle to the response object associated with this request.

Expand Down Expand Up @@ -205,6 +208,12 @@ res.send() are ignored.
### res.json(body)
Alias of res.send()

## Events

### 'finish'
Emitted the first time res.send is called, after the server has sent the message
to the socket. Does not imply that the client has received anything yet.

# Example

## Server
Expand Down Expand Up @@ -336,6 +345,8 @@ io.use(freshSocketRouter(myRouter));

# Todo
- Add "strict" option that responds to poorly formatted requests with 400.
- Implement SocketIoResponse 'close' event.
- Implement relevant SocketIoRequest events.

# Contributing

Expand Down
64 changes: 7 additions & 57 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
var Router = require('router');
var query = require('./middleware/query');
var SocketIoRequest = require('./request');
var SocketIoResponse = require('./response');

function FreshSocketIoRouter(router, options) {
opts = Object.create(options || null);
Expand All @@ -23,6 +25,11 @@ function FreshSocketIoRouter(router, options) {

// standard middleware
baseRouter.use(query());
//set req.ip
baseRouter.use(function(req, res, next) {
req.ip = req.socket.request.connection.remoteAddress;
next();
});

if(router instanceof Router) {
baseRouter.use(router);
Expand Down Expand Up @@ -106,62 +113,6 @@ function finalHandler(req, res, options) {
};
}

function SocketIoRequest (socket, route, message) {
this.socket = socket;
this.url = route || '/';
this.originalUrl = this.url;
this.message = message || {};
this.method = this.message.method && this.message.method.toUpperCase() || 'GET';
this.headers = this.message.headers || {};
this.body = this.message.body;
}

SocketIoRequest.prototype.method = 'GET';
SocketIoRequest.prototype.get = function(field) {
return this.headers && this.headers[field];
};
SocketIoRequest.prototype.header = SocketIoRequest.prototype.get;

function SocketIoResponse (socket, route) {
this.socket = socket;
this.headers = {};
this.sentResponse = false;
// emitUrl only goes up until the first question mark
this.emitUrl = route || '/';
var questionMarkIndex = this.emitUrl.indexOf('?');
if(questionMarkIndex !== -1) {
this.emitUrl = this.emitUrl.substring(0, questionMarkIndex);
}
}

SocketIoResponse.prototype.statusCode = 200;

SocketIoResponse.prototype.set = function(field, value) {
this.headers[field] = value;
};
SocketIoResponse.prototype.header = SocketIoResponse.prototype.set;

SocketIoResponse.prototype.status = function(code) {
this.statusCode = code;
return this;
};

SocketIoResponse.prototype.send = function(body) {
if(this.sentResponse) {
console.warn('WARNING: fresh-socketio-router: send: response has already been sent and will not be sent again');
return this;
}
var message = { status: this.statusCode, headers: this.headers };
if(body !== undefined) {
message.body = body;
}
this.socket.emit(this.emitUrl, message);
this.sentResponse = true;
return this;
};

SocketIoResponse.prototype.json = SocketIoResponse.prototype.send;

// status code names, taken from nodejs http module
var STATUS_CODES = exports.STATUS_CODES = {
100 : 'Continue',
Expand Down Expand Up @@ -231,4 +182,3 @@ var STATUS_CODES = exports.STATUS_CODES = {
module.exports = FreshSocketIoRouter;
module.exports.Router = Router;


24 changes: 24 additions & 0 deletions lib/request.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
var EventEmitter = require('events');
var util = require('util');

function SocketIoRequest (socket, route, message) {
EventEmitter.call(this);
this.socket = socket;
this.url = route || '/';
this.originalUrl = this.url;
this.message = message || {};
this.method = this.message.method && this.message.method.toUpperCase() || 'GET';
this.headers = this.message.headers || {};
this.body = this.message.body;
this.ip = this.socket.request.connection.remoteAddress;
}

util.inherits(SocketIoRequest, EventEmitter);

SocketIoRequest.prototype.method = 'GET';
SocketIoRequest.prototype.get = function(field) {
return this.headers && this.headers[field];
};
SocketIoRequest.prototype.header = SocketIoRequest.prototype.get;

module.exports = SocketIoRequest;
47 changes: 47 additions & 0 deletions lib/response.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
var EventEmitter = require('events');
var util = require('util');

function SocketIoResponse (socket, route) {
this.socket = socket;
this.headers = {};
this.sentResponse = false;
// emitUrl only goes up until the first question mark
this.emitUrl = route || '/';
var questionMarkIndex = this.emitUrl.indexOf('?');
if(questionMarkIndex !== -1) {
this.emitUrl = this.emitUrl.substring(0, questionMarkIndex);
}
}

util.inherits(SocketIoResponse, EventEmitter);

SocketIoResponse.prototype.statusCode = 200;

SocketIoResponse.prototype.set = function(field, value) {
this.headers[field] = value;
};
SocketIoResponse.prototype.header = SocketIoResponse.prototype.set;

SocketIoResponse.prototype.status = function(code) {
this.statusCode = code;
return this;
};

SocketIoResponse.prototype.send = function(body) {
if(this.sentResponse) {
console.warn('WARNING: fresh-socketio-router: send: response has already been sent and will not be sent again');
return this;
}
var message = { status: this.statusCode, headers: this.headers };
if(body !== undefined) {
message.body = body;
}
this.socket.emit(this.emitUrl, message);
this.emit('finish');
this.sentResponse = true;
return this;
};

SocketIoResponse.prototype.json = SocketIoResponse.prototype.send;

module.exports = SocketIoResponse;
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "fresh-socketio-router",
"version": "0.1.1",
"version": "0.1.2",
"description": "a middleware based router for socketio transactions",
"scripts": {
"test": "grunt test",
Expand Down Expand Up @@ -36,7 +36,7 @@
"travis-cov": "~0.2.5"
},
"engines": {
"node": ">=0.10"
"node": ">=0.11"
},
"config": {
"travis-cov": {
Expand Down
41 changes: 41 additions & 0 deletions test/FreshSocketIoRouter.js
Original file line number Diff line number Diff line change
Expand Up @@ -771,4 +771,45 @@ describe('FreshSocketIoRouter', function() {
]);
});
});
it('should have the response emit \'finish\' when res.send is called', function() {
var socketRouter = freshSocketRouter.Router();
var finishPromise;
socketRouter.use(function(req, res, next) {
finishPromise = new Promise(function(resolve, reject) {
res.on('finish', function() {
resolve();
});
});
next();
});
socketRouter.use('/test', function(req, res, next) {
res.status(200).send('hello ' + req.body);
});
io.use(freshSocketRouter(socketRouter));
var client = ioClient(ipAddress);
return new BPromise(function(resolve, reject) {
client.on('connect', function() {
resolve();
});
}).then(function() {
return BPromise.all([
new BPromise(function(resolve, reject) {
client.on('/test', function(data) {
expect(data).to.deep.equal({
status: 200,
headers: {},
body: 'hello hi'
});
resolve();
});
client.emit('/test', {
method: 'GET',
headers: {},
body: 'hi'
});
}),
finishPromise
]);
});
});
});

0 comments on commit 751ec21

Please sign in to comment.