Question

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);
    }
Was it helpful?

Solution

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

OTHER TIPS

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 :)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top