Copyright © 2009 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C liability, trademark and document use rules apply.
Designers of URIs have traditionally used ? to encode server-side parameters. At its inception, the Web also introduced fragment identifiers (preceded by # ) as a means of addressing specific locations in a document. As highly interactive applications get built using Web parts (HTML, CSS and JavaScript component resources that are themselves Web addressible see [tvr-cacm2009], there is an increasing need for encoding interaction state as part of the URI. The Web is beginning to discover and codify design patterns based on fragment identifiers for many of these use cases.
This document explores the issues that arise in this context, and attempts to define best practices that help:
The goal of this finding is to initially collect the various usage scenarios that are leading to innovative uses of client-side URI parameters, along with the solutions that have been developed by the Web community and make some architectural recommendations. We encourage the wider Web community to bring other usage scenarios and design patterns to our attention so that we maximize the chances of arriving at a final finding that helps move forward the architecture of the Web in a self-consistent manner.
This document has been developed for discussion by the W3C Technical Architecture Group and is being published as a Public Working Draft in order to get additional input from the Web community. This version, dated 30 November, 2010 is a follow-up to the previous version dated April 15, 2009. Sections that need additional work are intentionally left as empty place-holder sections so that the Web community gets a sense of where we would like to take this document.
Publication of this draft finding does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time.
Please send comments on this document to the publicly archived TAG mailing list www-tag@w3.org (archive ).
1 Introduction
2 Use Case Scenarios
2.1 Addressing
Into Multimedia Streams
2.1.1 Things to Note
2.1.2 Extrapolating From This Pattern
2.1.3 Architectural Questions
2.2 Interaction
State and Browser History
2.3 AJAX Libraries And
State Management
2.4 Web Command
Lines
2.5 The Naked
Hash-Ref
3 Recommended Best Practices
4 Affected Communities To Liaise
With
4.1 WHATWG:PushState()
5 Conclusions
6 References
At the beginning of the Web, it was decided to encode server-side URI parameters with a ? . At the same time, the Web adopted # to attach fragment identifiers to URIs so that user-agents could address into specific locations in an HTML document. Nearly 20 years later, the Web has built a strong set of conventions around how URI parameters are used. As transactional applications began moving on to the Web in the late 1990's, server-side parameters formed a core building block for how application state was communicated between client and server. In this phase of Web evolution, clients were still comparatively simple, and client-side URI parameters did not move beyond the use of fragment identifiers. But with Web 2.0 applications increasingly moving traditional client-side applications to the Web, we are now seeing a variety of design patterns emerging with respect to how client-side URI parameters are used in order to influence client interaction. The need to remain consistent with the prevalent Web architecture has seen these design patterns build on the existing mechanism of fragment identifiers in URIs. This finding enumerates the various emerging patterns along with their associated use cases as a means of documenting existing practice on the Web and makes some architectural recommendations.
This section enumerates the various usage scenarios that are leading to innovative uses of client-side URI parameters on the Web.
When publishing multimedia streams, there is often a need to address into specific points in the multimedia stream, e.g., by using a time-index. The simplest means of doing this is to pass in the start-time as a server-side parameter in the URI, e.g., http://www.example.com/media.stream?start=03:06:09 and have the server start streaming the content starting at 3 hours, 6 minutes and 9 seconds into the content. This has the additional side-benefit of creating distinct URIs for each point in the media stream and such URIs can be used to bookmark locations of interest.
It is also possible to leverage client-side parameters encoded as part of the URI (using a # ), where this pseudo fragment identifier is used by client-side scripts as an argument to be passed to an appropriate locator function. Consider the following example taken from cnn.com:
<a href="http://www.cnn.com/video/#/video/tech/2008/02/19/vo.aus.sea.spider.ap"> Giant sea spider filmed deep underwater </a>
CNN uses links like the above for all the topical video segments that are published on its site. The URI in this case has the following components:
Component | Value |
---|---|
Protocol | http |
Host | www.cnn.com |
Path | video |
Client Param | #/video/tech/2008/02/19/vo.aus.sea.spider.ap |
The browser is expected to do a GET of the URI leading up to the fragment, and the processing application, in this case, the JavaScript embedded in the HTML Response processes the portion of the URI following the # . Note that in the general case, the JavaScript function that eventually processes the client param may not have been present in the original HTTP Response it may come from a Javascript library that was loaded as the result of a subsequent HTTP GET request as a result of a script in the text/html response.
The fragment identifier has been intentionally identified as a
client parameter. Treating it as a regular fragment
identifier in this usage would result in one incorrectly inferring
that the URI for the video resource being addressed is
http://www.cnn.com/video
. This would result in all the
video links on the CNN site getting the same URI. Thus, the entire
URI in this case is
http://www.cnn.com/video/#/video/tech/2008/02/19/vo.aus.sea.spider.ap
.
A consumer of this URI who goes looking for an id
within the Response that matches the #-suffix of this URI
will fail. The reported Content-Type for the resource is
text/html
. However, the behavior of the
#-suffix
in this case is not defined by the HTML
specification.
As used, the #-suffix
is a first-class client
parameter in that it gets consumed by a script that is served
as part of the HTML document returned by the server upon receiving
a GET request. This embedded script examines the URI available to
it as script variable content.location
, strips off the
# and uses the rest of the prefix as an argument to function that
generates the actual URI. Having constructed this content URI, the
script then proceeds to instruct the browser to play the media at
the newly constructed location. Notice further that the behavior of
a user-agent that does not execute the embedded JavaScript is
different given this URI. Notice further that the HTTP Response
headers do not give the client any indication that this is likely
to be so.
The CNN example cited above is not unique with respect to its
use of #
within the URI for encoding parameters to the
receiving application. It shows that in a world of dynamic
documents, the traditional fragment identifier need no longer be an
idref
value that addresses an existing node in the
serialized HTML making up the HTTP Response. In addition to
possibly being a static idref
, the fragment identifier
in the URI, the pattern demonstrated here generalizes to the
following:
idref
to a dynamically generated node.This section enumerates some of the questions raised by this design pattern:
Content-Type
of
text/html
might assume (incorrectly) that the URI for
this video resource is
http://www.cnn.com/video.html
.A variety of methods are available in Web Architecture to save application state. Cookies store information on the client-side that is sent along with the GET request. Similarly, data can be stored on the server-side -- in a database, for example, identified by a cookie -- and can be used to change the details of the GET request. There are also specifications under development (See [Web Storage]) that extend the cookie mechanism in several directions. These specifications allow large amounts of data to be stored on the client and can also be used to encode application state.
These mechanisms, however, encode private applications states.
In some cases, an application may want to allow selected states to
be made public and shareable. For this we require a URI,
appropriately decorated with client-side and server-side
parameters. The challenge in designing a mechanism to encode state
is to preserve the familiar user experience especially to make the
back button do the right thing. For live examples of this design
pattern, see GMail and
Google Maps both of which
take extreme care to ensure that the back button works as
the user would expect. These applications use iframe
proxies to achieve the desired effect.
Consider Google Maps. When you open up the application it presents you with a default, high-level map. Then, as you enter location parameters, the map changes. You can also pan and zoom and move the map up, down or sideways.
Now, having zeroed in on the right map, you may want to save an identifier for it. Notice, however, that the address bar has not changed - it still says http://maps.google.com/. If you want a link to the displayed map, you click the "Link" button on the right and it gives you a URI to the map displayed.
http://maps.google.com/maps?f=q&source=s_q&hl=en&geocode=&q=212+Hessian+Hills+Rd,+Croton-on-Hudson,+NY+10520&sll=37.0625,-95.677068&sspn=32.527387,51.679688&ie=UTF8&hq=&hnear=212+Hessian+Hills+Rd,+Croton-on-Hudson,+Westchester,+New+York+10520&z=16
Notice the structure of this URI: it includes the address as well as other parameters. The URI that Google Maps creates for the displayed map has a long server-side parameter but no fragment identifier. This is because the maps are images and must be fetched from the server. If the maps were drawn using vector graphics, some of the scrolling and zooming could have been done on the client.
GMail, on the other hand,
uses fragment identifiers to encode the state. For example,
https://mail.google.com/mail/?shva=1#inbox/12c7e6abbc328af4
identifies the inbox and a specific piece of mail in the inbox. If
a piece of mail is not selected, the fragment identifier merely
identifies the inbox:
https://mail.google.com/mail/?shva=1#inbox
AJAX applications use features of Dynamic HTML (DHTML) to create
highly reactive user experiences. Updates to the Web user interface
in response to user actions no longer require a full page reload.
Consequently, the user can perform a sequence of interaction steps
while remaining on the same page at least as seen from the
browser's perspective of content.location
. This makes
for a good user experience, except for the following:
Today, many of the details of AJAX programming have been abstracted away by higher level toolkits such as [dojo] and [google-gwt]. Management of interaction state and browser history is one of the key affordances implemented in these libraries. History mechanisms in AJAX libraries like GWT and Dojo share a lot in common, and the approach can be traced back to Really Simple History (RSH). In addition, the mechanism described here has also been adopted by a recent update to GMail.
The basic premise is to keep track of the application's internal state in the URI fragment identifier. This works because updating the fragment doesn't typically cause the page to be reloaded. This approach has several benefits:
bookmarkable
i.e., the user can create a
bookmark to the current state and save it, email it, or
whatever.One of the techniques that is used to provide this functionality
is to open a number of frames within a browser window. In such an
architecture, parent and child frames are allowed to change each
others' location
URI as long as the frames display
information from the same domain or have agreed to collaborate by
some other means. Otherwise, changing a frame's
location
URI opens up a cross-site scripting hole. If
the frames can collaborate, then one of the frames, say the parent,
passes data to the child via a fragment identifier by reseting the
child's location
URI. Thus, given a parent frame
P
and a child frame C
, where the
location URIs U_P
and U_C
may come from
different domains, the parent frame might pass data to the child by
resetting its location URI to U_C#data
; the child
picks up this data by polling for changes in its location URI. This
technique is used in Comet
Programming. As an example, the Dojo AJAX toolkit uses an
IFrame proxy
to enable cross-domain XML HTTP Requests.
this is a useful technique when writing cross-site mashups. As an
example, see XKCD and
AxsJAX a cross-site mashup that mashes together XKCD comics
with their associated transcripts to create a speech-friendly XKCD
experience.
When applications can be built of Web parts, there is a need to
configure them at the point the application is launched.
Traditional applications would call these default start-up or
command-line options. We see the equivalent emerging for
configuring desktop gadgets and widgets where command-line options
are passed in via URI parameters in this context, the URI is the
Web command-line. For one sample implementation and its associated
usage, see
Using URIs To Pass Parameters To The Web. Dave Raggett's
HTMLSlidy
uses URIs of the form ...#(nn)
to address into a deck
of slides.
As the final item in the usage scenarios as seen on the Web,
this section documents the use of a single #
sign as
the value of the href
attribute on HTML anchors. This
can be thought of as a relative URI with a null
fragment identifier. Web sites wishing to override the
default-target behavior of anchors use this when attaching
a JavaScript event-handler to anchor elements for mouse-clicks. The
only justification to place a naked #
as the value of
the href attribute appears to be to avoid anything showing up on
the browser status bar as the user activates the link. Note that
this idiom also creates significant hurdles for non-mouse users of
the Web.
Applications that choose to make some states public and shareable should use framnet identifiers to identify such staes.
We will need to liaise effectively with standard groups that are active in defining the formats and protocols that come together in turning an HTTP Response into an interactive user interface for a Web application. This section will be used to track these dependencies, and may be removed upon final publication of this document.
The WhatWG that presently defines the behavior of conforming HTML5 Web browsers in conjunction with the W3C HTMLWG. There is also ongoing HTTP work in the IETF.
There is ongoing discussion regarding encoding client-side state in the WHATWG by using pushState() which allows for changing the whole URI using ECMAScript so that the URI exposed to copy-and-paste can still make sense in contexts without scripting. It also addresses the back button concern.See pushState().
As the Web has evolved from showing things to doing things the fragment identifier has been repurposed to indicate a broad range of functionality. This document discusses some of these uses. We would be grateful for feedback showing other uses of the fragment identifier.