views:

137

answers:

2

I have the following HttpHandler; I'm using it to push updates to the browser (where jQuery and GrowlUI are implemented) without the need for the browser to poll. I think all I've accomplished is moving the polling loop to the server.

Can anyone tell me how I can make this class more robust and scalable?

Here is the code.

public class LiveUpdates : IHttpHandler
{
    //TODO: Replace this with a repository that the application can log to.
    private static readonly Dictionary<string, Queue<string>> updateQueue;
    static LiveUpdates()
    {
        updateQueue = new Dictionary<string, Queue<string>>();
    }

    public void ProcessRequest(HttpContext context)
    {
        context.Response.Buffer = true;

        while (context.Response.IsClientConnected)
        {
            if (context.User == null) return;
            if (!context.User.Identity.IsAuthenticated) return;

            Thread.Sleep(1000);
            if (!updateQueue.ContainsKey(context.User.Identity.Name)) continue;
            if (updateQueue[context.User.Identity.Name].Count == 0) continue;

            GrowlStatus(context.Response, updateQueue[context.User.Identity.Name].Dequeue());
        }


    }

    protected static void GrowlStatus(HttpResponse Response, string Message)
    {
        // Write out the parent script callback.
        Response.Write(String.Format("<script type=\"text/javascript\">parent.$.growlUI('Message', '{0}');</script>", Message));
        // To be sure the response isn't buffered on the server.    
        Response.Flush();
    }

    public static void QueueUpdate(IPrincipal User, string UpdateMessage)
    {
        if (!updateQueue.ContainsKey(User.Identity.Name))
        {
            updateQueue.Add(User.Identity.Name, new Queue<string>());
        }
        updateQueue[User.Identity.Name].Enqueue(UpdateMessage);
    }

    public static void ClearUpdates(IPrincipal User)
    {
        if (updateQueue.ContainsKey(User.Identity.Name)) updateQueue.Remove(User.Identity.Name);
    }
+1  A: 

How is QueueUpdate called? I noticed you take strings from that and place it directly into the javascript you are sending back to the user. Is there any chance a user could insert javascript into an entry and have QueueUpdate somehow display it back?

Also, I would match Message against a valid message regex before putting it into your javascript string. It seems like someone could complete your growlUi call and then insert their own javascript pretty easily. At the very least you could make sure the Message you are inserting does not contain a single quote (') which could terminate the string and begin a new javascript command.

Maybe that's just paranoia, but it will make it more robust :)

Doug T.
Thanks, I will keep this in mind also :)
almog.ori
Lol, I guess you weren't asking about "robust in general"
Doug T.
+2  A: 

If you plan to use Thread.Sleep(), you MUST implement System.Web.IHttpAsyncHandler or your handler will not scale.

Rubens Farias
Interesting I will look into this.
almog.ori
also read this: http://stackoverflow.com/questions/1574216/bandwidth-throttling-for-file-download
Rubens Farias
Did you solve this issue?
almog.ori
yes, I just couldn't post answer yet cause I'm inspecting a multirequest issue, but its probably related to my source
Rubens Farias