Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: mohlendo/node_chat
base: master
...
head fork: ramons03/node_chat
compare: master
Checking mergeability… Don't worry, you can still create the pull request.
  • 17 commits
  • 6 files changed
  • 0 commit comments
  • 7 contributors
Commits on Dec 18, 2009
Mark Muskardin posix module not included - could not start server - error on line 73…
… of fu.js (process.cat)
6c4ef86
Commits on Jan 09, 2010
@ulf ulf Reworked example to work with current version of node.js 957a91a
Commits on Jan 12, 2010
@ry ry Add license file 8e39ed8
Commits on Feb 17, 2010
@ry ry Update for node v0.1.29 eb15bed
Commits on Feb 21, 2010
@ry ry Upgrade for node 0.1.30-pre 4c2709c
@ry ry Always convert input to string - found bug where it was an integer b7850da
Commits on Mar 14, 2010
@aaronblohowiak aaronblohowiak Reformatting for readability 985cb47
Commits on Mar 17, 2010
@aaronblohowiak aaronblohowiak Added comments, removed trailing whitespace 1f063fc
@aaronblohowiak aaronblohowiak update document.title to show unread when blurred 7935af4
Commits on May 10, 2010
@ry ry Update for v0.1.94 f2d65d9
Commits on May 23, 2010
@ry ry Add RSS and uptime display 8ec8bb2
Commits on Jun 16, 2010
@bensonk bensonk Fixed a bug in fu's handling of HEAD requests.
The fu.js code wasn't checking to see if a request method was HEAD.
That resulted in it sending a body to a head request.  This in turn
resulted in breaking the spec which the underlying Node library didn't
like.  In turn, this resulted in an uncaught exception which crashed the
server. Now if the request type is HEAD, it does the right thing.
f5f9f1f
Commits on Aug 18, 2010
@ry ry Add default port for heroku 1787c0f
Commits on Nov 23, 2010
@fly-away fly-away Fix unicode support f72a42e
Commits on Apr 02, 2012
ramons03 web.config f57aebd
ramons03 nodejstest 959caf3
ramons03 test 07ceebf
Showing with 327 additions and 69 deletions.
  1. +19 −0 LICENSE-MIT
  2. +228 −6 client.js
  3. +31 −39 fu.js
  4. +2 −1  index.html
  5. +39 −23 server.js
  6. +8 −0 web.config
View
19 LICENSE-MIT
@@ -0,0 +1,19 @@
+Copyright 2009,2010 Ryan Dahl <ry@tinyclouds.org>
+
+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.
View
234 client.js
@@ -1,33 +1,144 @@
var CONFIG = { debug: false
, nick: "#" // set in onConnect
, id: null // set in onConnect
- , last_message_time: 0
+ , last_message_time: 1
+ , focus: true //event listeners bound in onConnect
+ , unread: 0 //updated in the message-processing loop
};
var nicks = [];
+// CUT ///////////////////////////////////////////////////////////////////
+/* This license and copyright apply to all code until the next "CUT"
+http://github.com/jherdman/javascript-relative-time-helpers/
+
+The MIT License
+
+Copyright (c) 2009 James F. Herdman
+
+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.
+
+
+ * Returns a description of this past date in relative terms.
+ * Takes an optional parameter (default: 0) setting the threshold in ms which
+ * is considered "Just now".
+ *
+ * Examples, where new Date().toString() == "Mon Nov 23 2009 17:36:51 GMT-0500 (EST)":
+ *
+ * new Date().toRelativeTime()
+ * --> 'Just now'
+ *
+ * new Date("Nov 21, 2009").toRelativeTime()
+ * --> '2 days ago'
+ *
+ * // One second ago
+ * new Date("Nov 23 2009 17:36:50 GMT-0500 (EST)").toRelativeTime()
+ * --> '1 second ago'
+ *
+ * // One second ago, now setting a now_threshold to 5 seconds
+ * new Date("Nov 23 2009 17:36:50 GMT-0500 (EST)").toRelativeTime(5000)
+ * --> 'Just now'
+ *
+ */
+Date.prototype.toRelativeTime = function(now_threshold) {
+ var delta = new Date() - this;
+
+ now_threshold = parseInt(now_threshold, 10);
+
+ if (isNaN(now_threshold)) {
+ now_threshold = 0;
+ }
+
+ if (delta <= now_threshold) {
+ return 'Just now';
+ }
+
+ var units = null;
+ var conversions = {
+ millisecond: 1, // ms -> ms
+ second: 1000, // ms -> sec
+ minute: 60, // sec -> min
+ hour: 60, // min -> hour
+ day: 24, // hour -> day
+ month: 30, // day -> month (roughly)
+ year: 12 // month -> year
+ };
+
+ for (var key in conversions) {
+ if (delta < conversions[key]) {
+ break;
+ } else {
+ units = key; // keeps track of the selected key over the iteration
+ delta = delta / conversions[key];
+ }
+ }
+
+ // pluralize a unit when the difference is greater than 1.
+ delta = Math.floor(delta);
+ if (delta !== 1) { units += "s"; }
+ return [delta, units].join(" ");
+};
+
+/*
+ * Wraps up a common pattern used with this plugin whereby you take a String
+ * representation of a Date, and want back a date object.
+ */
+Date.fromString = function(str) {
+ return new Date(Date.parse(str));
+};
+
+// CUT ///////////////////////////////////////////////////////////////////
+
+
+
+//updates the users link to reflect the number of active users
function updateUsersLink ( ) {
var t = nicks.length.toString() + " user";
if (nicks.length != 1) t += "s";
$("#usersLink").text(t);
}
+//handles another person joining chat
function userJoin(nick, timestamp) {
+ //put it in the stream
addMessage(nick, "joined", timestamp, "join");
+ //if we already know about this user, ignore it
for (var i = 0; i < nicks.length; i++)
if (nicks[i] == nick) return;
+ //otherwise, add the user to the list
nicks.push(nick);
+ //update the UI
updateUsersLink();
}
+//handles someone leaving
function userPart(nick, timestamp) {
+ //put it in the stream
addMessage(nick, "left", timestamp, "part");
+ //remove the user from the list
for (var i = 0; i < nicks.length; i++) {
if (nicks[i] == nick) {
nicks.splice(i,1)
break;
}
}
+ //update the UI
updateUsersLink();
}
@@ -38,11 +149,16 @@ util = {
// html sanitizer
toStaticHTML: function(inputHtml) {
+ inputHtml = inputHtml.toString();
return inputHtml.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;");
},
+ //pads n with zeros on the left,
+ //digits is minimum length of output
+ //zeroPad(3, 5); returns "005"
+ //zeroPad(2, 500); returns "500"
zeroPad: function (digits, n) {
n = n.toString();
while (n.length < digits)
@@ -50,23 +166,31 @@ util = {
return n;
},
+ //it is almost 8 o'clock PM here
+ //timeString(new Date); returns "19:49"
timeString: function (date) {
var minutes = date.getMinutes().toString();
var hours = date.getHours().toString();
return this.zeroPad(2, hours) + ":" + this.zeroPad(2, minutes);
},
+ //does the argument only contain whitespace?
isBlank: function(text) {
var blank = /^\s*$/;
return (text.match(blank) !== null);
}
};
+//used to keep the most recent messages visible
function scrollDown () {
window.scrollBy(0, 100000000000000000);
$("#entry").focus();
}
+//inserts an event into the stream for display
+//the event may be a msg, join or part type
+//from is the user, text is the body and time is the timestamp, defaulting to now
+//_class is a css class to apply to the message, usefull for system events
function addMessage (from, text, time, _class) {
if (text === null)
return;
@@ -79,6 +203,10 @@ function addMessage (from, text, time, _class) {
time = new Date(time);
}
+ //every message you see is actually a table with 3 cols:
+ // the time,
+ // the person who caused the event,
+ // and the content
var messageElement = $(document.createElement("table"));
messageElement.addClass("message");
@@ -88,7 +216,7 @@ function addMessage (from, text, time, _class) {
// sanitize
text = util.toStaticHTML(text);
- // See if it matches our nick?
+ // If the current user said this, add a special css class
var nick_re = new RegExp(CONFIG.nick);
if (nick_re.exec(text))
messageElement.addClass("personal");
@@ -104,28 +232,63 @@ function addMessage (from, text, time, _class) {
;
messageElement.html(content);
+ //the log is the stream that we view
$("#log").append(messageElement);
+
+ //always view the most recent message when it is added
scrollDown();
}
+function updateRSS () {
+ var bytes = parseInt(rss);
+ if (bytes) {
+ var megabytes = bytes / (1024*1024);
+ megabytes = Math.round(megabytes*10)/10;
+ $("#rss").text(megabytes.toString());
+ }
+}
+
+function updateUptime () {
+ if (starttime) {
+ $("#uptime").text(starttime.toRelativeTime());
+ }
+}
+
var transmission_errors = 0;
var first_poll = true;
+
+//process updates if we have any, request updates from the server,
+// and call again with response. the last part is like recursion except the call
+// is being made from the response handler, and not at some point during the
+// function's execution.
function longPoll (data) {
if (transmission_errors > 2) {
showConnect();
return;
}
+ if (data && data.rss) {
+ rss = data.rss;
+ updateRSS();
+ }
+
+ //process any updates we may have
+ //data will be null on the first call of longPoll
if (data && data.messages) {
for (var i = 0; i < data.messages.length; i++) {
var message = data.messages[i];
+ //track oldest message so we only request newer messages from server
if (message.timestamp > CONFIG.last_message_time)
CONFIG.last_message_time = message.timestamp;
+ //dispatch new messages to their appropriate handlers
switch (message.type) {
case "msg":
+ if(!CONFIG.focus){
+ CONFIG.unread++;
+ }
addMessage(message.nick, message.text, message.timestamp);
break;
@@ -138,12 +301,17 @@ function longPoll (data) {
break;
}
}
+ //update the document title to include unread message count if blurred
+ updateTitle();
+
+ //only after the first request for messages do we want to show who is here
if (first_poll) {
first_poll = false;
who();
}
}
+ //make another request
$.ajax({ cache: false
, type: "GET"
, url: "/recv"
@@ -152,22 +320,31 @@ function longPoll (data) {
, error: function () {
addMessage("", "long poll error. trying again...", new Date(), "error");
transmission_errors += 1;
+ //don't flood the servers on error, wait 10 seconds before retrying
setTimeout(longPoll, 10*1000);
}
, success: function (data) {
transmission_errors = 0;
+ //if everything went well, begin another request immediately
+ //the server will take a long time to respond
+ //how long? well, it will wait until there is another message
+ //and then it will return it to us and close the connection.
+ //since the connection is closed when we get data, we longPoll again
longPoll(data);
}
});
}
+//submit a new message to the server
function send(msg) {
if (CONFIG.debug === false) {
// XXX should be POST
+ // XXX should add to messages immediately
jQuery.get("/send", {id: CONFIG.id, text: msg}, function (data) { }, "json");
}
}
+//Transition the page to the state that prompts the user for a nickname
function showConnect () {
$("#connect").show();
$("#loading").hide();
@@ -175,12 +352,14 @@ function showConnect () {
$("#nickInput").focus();
}
+//transition the page to the loading screen
function showLoad () {
$("#connect").hide();
$("#loading").show();
$("#toolbar").hide();
}
+//transition the page to the main chat view, putting the cursor in the textfield
function showChat (nick) {
$("#toolbar").show();
$("#entry").focus();
@@ -191,6 +370,21 @@ function showChat (nick) {
scrollDown();
}
+//we want to show a count of unread messages when the window does not have focus
+function updateTitle(){
+ if (CONFIG.unread) {
+ document.title = "(" + CONFIG.unread.toString() + ") node chat";
+ } else {
+ document.title = "node chat";
+ }
+}
+
+// daemon start time
+var starttime;
+// daemon memory usage
+var rss;
+
+//handle the server's response to our nickname and join request
function onConnect (session) {
if (session.error) {
alert("error connecting: " + session.error);
@@ -200,16 +394,35 @@ function onConnect (session) {
CONFIG.nick = session.nick;
CONFIG.id = session.id;
+ starttime = new Date(session.starttime);
+ rss = session.rss;
+ updateRSS();
+ updateUptime();
+ //update the UI to show the chat
showChat(CONFIG.nick);
+
+ //listen for browser events so we know to update the document title
+ $(window).bind("blur", function() {
+ CONFIG.focus = false;
+ updateTitle();
+ });
+
+ $(window).bind("focus", function() {
+ CONFIG.focus = true;
+ CONFIG.unread = 0;
+ updateTitle();
+ });
}
+//add a list of present chat members to the stream
function outputUsers () {
var nick_string = nicks.length > 0 ? nicks.join(", ") : "(none)";
addMessage("users:", nick_string, new Date(), "notice");
return false;
}
+//get a list of the users presently in the room, and add it to the stream
function who () {
jQuery.get("/who", {}, function (data, status) {
if (status != "success") return;
@@ -220,6 +433,7 @@ function who () {
$(document).ready(function() {
+ //submit new messages when the user hits enter if the message isnt blank
$("#entry").keypress(function (e) {
if (e.keyCode != 13 /* Return */) return;
var msg = $("#entry").attr("value").replace("\n", "");
@@ -229,22 +443,27 @@ $(document).ready(function() {
$("#usersLink").click(outputUsers);
+ //try joining the chat when the user clicks the connect button
$("#connectButton").click(function () {
+ //lock the UI while waiting for a response
showLoad();
var nick = $("#nickInput").attr("value");
+ //dont bother the backend if we fail easy validations
if (nick.length > 50) {
alert("Nick too long. 50 character max.");
showConnect();
return false;
}
+ //more validations
if (/[^\w_\-^!]/.exec(nick)) {
alert("Bad character in nick. Can only have letters, numbers, and '_', '-', '^', '!'");
showConnect();
return false;
}
+ //make the actual join request to the server
$.ajax({ cache: false
, type: "GET" // XXX should be POST
, dataType: "json"
@@ -259,11 +478,10 @@ $(document).ready(function() {
return false;
});
- // update the clock every second
+ // update the daemon uptime every 10 seconds
setInterval(function () {
- var now = new Date();
- $("#currentTime").text(util.timeString(now));
- }, 1000);
+ updateUptime();
+ }, 10*1000);
if (CONFIG.debug) {
$("#loading").hide();
@@ -275,11 +493,15 @@ $(document).ready(function() {
// remove fixtures
$("#log table").remove();
+ //begin listening for updates right away
+ //interestingly, we don't need to join a room to get its updates
+ //we just don't show the chat stream to the user until we create a session
longPoll();
showConnect();
});
+//if we can, notify the server that we're going away.
$(window).unload(function () {
jQuery.get("/part", {id: CONFIG.id}, function (data) { }, "json");
});
View
70 fu.js
@@ -1,5 +1,7 @@
var createServer = require("http").createServer;
+var readFile = require("fs").readFile;
var sys = require("sys");
+var url = require("url");
DEBUG = false;
var fu = exports;
@@ -7,11 +9,10 @@ var fu = exports;
var NOT_FOUND = "Not Found\n";
function notFound(req, res) {
- res.sendHeader(404, [ ["Content-Type", "text/plain"]
- , ["Content-Length", NOT_FOUND.length]
- ]);
- res.sendBody(NOT_FOUND);
- res.finish();
+ res.writeHead(404, { "Content-Type": "text/plain"
+ , "Content-Length": NOT_FOUND.length
+ });
+ res.end(NOT_FOUND);
}
var getMap = {};
@@ -19,26 +20,23 @@ var getMap = {};
fu.get = function (path, handler) {
getMap[path] = handler;
};
-
var server = createServer(function (req, res) {
if (req.method === "GET" || req.method === "HEAD") {
- var handler = getMap[req.uri.path] || notFound;
+ var handler = getMap[url.parse(req.url).pathname] || notFound;
res.simpleText = function (code, body) {
- res.sendHeader(code, [ ["Content-Type", "text/plain"]
- , ["Content-Length", body.length]
- ]);
- res.sendBody(body);
- res.finish();
+ res.writeHead(code, { "Content-Type": "text/plain"
+ , "Content-Length": body.length
+ });
+ res.end(body);
};
res.simpleJSON = function (code, obj) {
- var body = JSON.stringify(obj);
- res.sendHeader(code, [ ["Content-Type", "text/json"]
- , ["Content-Length", body.length]
- ]);
- res.sendBody(body);
- res.finish();
+ var body = new Buffer(JSON.stringify(obj));
+ res.writeHead(code, { "Content-Type": "text/json"
+ , "Content-Length": body.length
+ });
+ res.end(body);
};
handler(req, res);
@@ -60,7 +58,6 @@ function extname (path) {
fu.staticHandler = function (filename) {
var body, headers;
var content_type = fu.mime.lookupExtension(extname(filename));
- var encoding = (content_type.slice(0,4) === "text" ? "utf8" : "binary");
function loadResponseData(callback) {
if (body && headers && !DEBUG) {
@@ -69,30 +66,25 @@ fu.staticHandler = function (filename) {
}
sys.puts("loading " + filename + "...");
- var promise = process.fs.cat(filename, encoding);
-
- promise.addCallback(function (data) {
- body = data;
- headers = [ [ "Content-Type" , content_type ]
- , [ "Content-Length" , body.length ]
- ];
- if (!DEBUG)
- headers.push(["Cache-Control", "public"]);
-
- sys.puts("static file " + filename + " loaded");
- callback();
- });
-
- promise.addErrback(function () {
- sys.puts("Error loading " + filename);
+ readFile(filename, function (err, data) {
+ if (err) {
+ sys.puts("Error loading " + filename);
+ } else {
+ body = data;
+ headers = { "Content-Type": content_type
+ , "Content-Length": body.length
+ };
+ if (!DEBUG) headers["Cache-Control"] = "public";
+ sys.puts("static file " + filename + " loaded");
+ callback();
+ }
});
}
return function (req, res) {
loadResponseData(function () {
- res.sendHeader(200, headers);
- res.sendBody(body, encoding);
- res.finish();
+ res.writeHead(200, headers);
+ res.end(req.method === "HEAD" ? "" : body);
});
}
};
@@ -103,7 +95,7 @@ fu.mime = {
lookupExtension : function(ext, fallback) {
return fu.mime.TYPES[ext.toLowerCase()] || fallback || 'application/octet-stream';
},
-
+
// List of most common mime-types, stolen from Rack.
TYPES : { ".3gp" : "video/3gpp"
, ".a" : "application/octet-stream"
View
3  index.html
@@ -179,8 +179,9 @@
</div>
<div id="toolbar">
<ul id="status">
- <li class="date" id="currentTime">12:59</li>
<li><a id="usersLink" href="#">5 users</a></li>
+ <li>uptime: <span id="uptime">?</span></li>
+ <li>memory: <span id="rss">?</span>mb RSS</li>
</ul>
<input tabindex="1" type="text" id="entry"/>
</div>
View
62 server.js
@@ -1,15 +1,27 @@
HOST = null; // localhost
PORT = 8001;
-var fu = require("./fu");
-var sys = require("sys");
+// when the daemon started
+var starttime = (new Date()).getTime();
-var MESSAGE_BACKLOG = 200;
-var SESSION_TIMEOUT = 60 * 1000;
+var mem = process.memoryUsage();
+// every 10 seconds poll for the memory.
+setInterval(function () {
+ mem = process.memoryUsage();
+}, 10*1000);
+
+
+var fu = require("./fu"),
+ sys = require("sys"),
+ url = require("url"),
+ qs = require("querystring");
+
+var MESSAGE_BACKLOG = 200,
+ SESSION_TIMEOUT = 60 * 1000;
var channel = new function () {
- var messages = [];
- var callbacks = [];
+ var messages = [],
+ callbacks = [];
this.appendMessage = function (nick, type, text) {
var m = { nick: nick
@@ -62,7 +74,7 @@ var channel = new function () {
while (callbacks.length > 0 && now - callbacks[0].timestamp > 30*1000) {
callbacks.shift().callback([]);
}
- }, 1000);
+ }, 3000);
};
var sessions = {};
@@ -78,9 +90,7 @@ function createSession (nick) {
var session = {
nick: nick,
-
id: Math.floor(Math.random()*99999999999).toString(),
-
timestamp: new Date(),
poke: function () {
@@ -110,7 +120,7 @@ setInterval(function () {
}
}, 1000);
-fu.listen(PORT, HOST);
+fu.listen(Number(process.env.PORT || PORT), HOST);
fu.get("/", fu.staticHandler("index.html"));
fu.get("/style.css", fu.staticHandler("style.css"));
@@ -125,11 +135,13 @@ fu.get("/who", function (req, res) {
var session = sessions[id];
nicks.push(session.nick);
}
- res.simpleJSON(200, { nicks: nicks });
+ res.simpleJSON(200, { nicks: nicks
+ , rss: mem.rss
+ });
});
fu.get("/join", function (req, res) {
- var nick = req.uri.params["nick"];
+ var nick = qs.parse(url.parse(req.url).query).nick;
if (nick == null || nick.length == 0) {
res.simpleJSON(400, {error: "Bad nick."});
return;
@@ -143,51 +155,55 @@ fu.get("/join", function (req, res) {
//sys.puts("connection: " + nick + "@" + res.connection.remoteAddress);
channel.appendMessage(session.nick, "join");
- res.simpleJSON(200, { id: session.id, nick: session.nick});
+ res.simpleJSON(200, { id: session.id
+ , nick: session.nick
+ , rss: mem.rss
+ , starttime: starttime
+ });
});
fu.get("/part", function (req, res) {
- var id = req.uri.params.id;
+ var id = qs.parse(url.parse(req.url).query).id;
var session;
if (id && sessions[id]) {
session = sessions[id];
session.destroy();
}
- res.simpleJSON(200, { });
+ res.simpleJSON(200, { rss: mem.rss });
});
fu.get("/recv", function (req, res) {
- if (!req.uri.params.since) {
+ if (!qs.parse(url.parse(req.url).query).since) {
res.simpleJSON(400, { error: "Must supply since parameter" });
return;
}
- var id = req.uri.params.id;
+ var id = qs.parse(url.parse(req.url).query).id;
var session;
if (id && sessions[id]) {
session = sessions[id];
session.poke();
}
- var since = parseInt(req.uri.params.since, 10);
+ var since = parseInt(qs.parse(url.parse(req.url).query).since, 10);
channel.query(since, function (messages) {
if (session) session.poke();
- res.simpleJSON(200, { messages: messages });
+ res.simpleJSON(200, { messages: messages, rss: mem.rss });
});
});
fu.get("/send", function (req, res) {
- var id = req.uri.params.id;
- var text = req.uri.params.text;
+ var id = qs.parse(url.parse(req.url).query).id;
+ var text = qs.parse(url.parse(req.url).query).text;
var session = sessions[id];
if (!session || !text) {
res.simpleJSON(400, { error: "No such session id" });
- return;
+ return;
}
session.poke();
channel.appendMessage(session.nick, "msg", text);
- res.simpleJSON(200, {});
+ res.simpleJSON(200, { rss: mem.rss });
});
View
8 web.config
@@ -0,0 +1,8 @@
+<configuration>
+ <system.webServer>
+ <handlers>
+ <add name="iisnode" path="server.js" verb="*" modules="iisnode" />
+ </handlers>
+ <iisnode loggingEnabled="false" />
+ </system.webServer>
+</configuration>

No commit comments for this range

Something went wrong with that request. Please try again.