Window id campaign – leverage the HTTP session
What is the idea about?
When writing web applications it is always problematic to make use of the HTTP session. The HTTP session is stored as cooky on the client and is shared across all browser windows. Those problems could be solved, if the browser sent an id which is unique per browser window.
This article describes the problem and the window id approach.
Links
Some practical use cases
A Firefox plugin to explore a browser with window id
A sample application illustrating the use of a window id
Current discussion in the public webapp work group
Current discussion on the whatwg mailing list
Discussion in the Web Kit mailing list
First discussion in the Mozilla mailing list
Discussion of use cases in the Mozilla mailing list
The problem of session usage
To simplify web development it would be great if all browser support the feature, I will describe later in this article. First, I would like to illustrate the problem.
HTTP is a stateless technology. IF a browser sends a GET request, it will receive a page. This conflicts frequently with web applications. Imagine an application to edit an article. You select an article to edit and would like to add a couple of paragraphs and save the article at the end. This requires that your web applications stores the not yet saved paragraphs to your article either on the client or on the server.
To store the paragraphs on the client you could add them as hidden input field to your form. To improve security you could encrypt those fields as well.
Sample form storing the state on the client.
<form action="/foo" method="post"> <input value="bla bla" name="paragraph[0]" type="hidden" > <input value="bla bla" name="paragraph[1]" type="hidden" > <textarea name="new_paragraph"></textarea> <input type="submit"> </form>
The disadvantage of this approach is that your form grows rapidly. Every request sends around all paragraphs. This is by far not efficient.
A more efficient approach is to store the state on the server. This is normally done using a session. The session id itself is stored in a cooky on the browser. Using Java we will find code like the following:
First when we start editing
session.setAttribute("article", article);
Later when we add a paragraph
Article article = (Article) session.getAttribute("article"); article.addParagraph(request.getParameter("new_paragraph");
The caveat of this approach is, if the user opens the same application in a new browser window or tabular and starts to edit another article. In that case the tab which was opened first will add paragraphs to the article selected by the tab opened secondly.
There is no way for a developer to find out that the user has silently copied the URL and pasted it into a new tab and there is no option to store data per window in the user session.
The solution with a window id
The browser should generate an id unique per browser window and sent it as request header with every browser request.
Request Header
X-Window-Id: 279078917624897
This allows to identify which windows sent a request and helps to leverage the use of the HTTP session in multi page web application. I will describe this in more detail below.
Why is it useful?
Imagine you want to use accordion style menus (sample: JQuery UI – http://jqueryui.com/demos/accordion/) or menu groups like the one of JSF Richfaces (http://livedemo.exadel.com/richfaces-demo/richfaces/panelMenu.jsf?c=panelMenu&tab=usage).
If you want to show the same menus or widgets opened after a page reload, then you need to memorize somehow what is opened or closed. We need to keep track of the application’s state.
Using the REQUEST
We could store the information in the request. As a consequence, every form and link of our screen needs to include a list of opened menus/widgets. This could be achieved by manipulating all links and forms using JavaScript.
The advantage is that it works with multiple windows and does not require a user session. The disadvantage is that it pollutes the request and enlarges the data sent by every request. In an application with a lot of stateful information it could be impossible to follow this approach.
Using the SESSION
The other solution is to store the state in the users session. Every time a menu/widget is opened, we send an Ajax request to keep track of opened menus. The downside of session usage is that it is impossible to use multiple windows in the browser because they would overwrite other window’s state (opened menus). This is because a user session is normally stored as browser cookie and cookies are merged into a single space for all browser windows (new exception: secure browser windows)
Using the window id
Having a window id, we can save the list of opened menus/widgets per window in the user session. We split up the user session in slices. In pseudocode it looks like this:
id = request[‘x-window-id’]
context = session[id]
menus = context[‘menus’]
It is quite interesting that HTML 5 solves the problem for the client side of JavaScript applications. The sessionStorage allows fine grained control if data is seen by all windows or just by the current. The problem only persists for client – server applications.
Another use case are dialogs or conversations which span multiple pages. We could think of a complex dialog to edit an item or the checkout process of a shop application. With a windows id, we know that the complex dialog was started in a window and that the user is now visiting another area. This allows to clean up the session area for this window.
I created a plugin for Firefox which adds the window-id to a request. You can use my ruby based sample application to test the be behavior.
Best Regards/Viele Grüße
Sebastian Hennebrueder