AJAX Considered Harmful
Please pardon the provocative title, but this post is intended to surface one point I buried in yesterday’s presentation in the hopes that by making it a separate post it will attract a wider audience.
I intend for this to post to be constructive, so I will focus on two specific suggestions which hopefully will serve as the seed for the development of a set of best practices for AJAX. Here are the two humble suggestions on things that people should standardize on:
- the data should first be encoded as octets according to the UTF-8 character encoding
- GET should never be used to initiate another operation which will change state
Rationale for these two suggestions follows.
Encoding
For the former, I proposed a simple test:
The first thing I want you to do is to copy the string “Iñtërnâtiônàlizætiøn” into your tool and observe what comes out the other side.
When expressed as a part of the query component of a URI, it
should look like
I%C3%B1t%C3%ABrn%C3%A2ti%C3%B4n%C3%A0liz%C3%A6ti%C3%B8n.
Standardizing improves interoperability, and the reason why I am suggesting UTF-8 is that it is backwards compatible with ASCII, can express the full range of the Unicode character set, and is widely implemented.
Idempotency
Looking into the current PHP implementation of SAJAX, you will see the following:
// Bust cache in the head
header ("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // Date in the past
header ("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
// always modified
header ("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header ("Pragma: no-cache"); // HTTP/1.0
This code should be a rather large clue that you are probably doing something wrong. Apparently the author recognized that these headers are somewhat sporadically and inconsistently implemented, and hoped that by combining them that the chances of success would be improved.
The danger that the responses may be cached is actually the smaller of several concerns. A much bigger concern is that unsuspecting grandmothers and bots everywhere can be tricked into modifying online databases simply by following a link.
Judicious use of HTTP GET can be a very good thing.
Perhaps toolkits can adopt a convention that procedure names that
start with the characters “Get” use GET,
everything else uses POST.
I may share some blame in that have dropped notes under XMLHttpRequest Caching.
IE’s XMLHTTP object caches GET requests while Mozilla’s (and probably the KJS version) don’t. That get’s into a fine line between what’s Javascript’s job and what’s the browser’s job.
The problem is if you have a method like “GetNewest”. Guess there’s a RPC discussion lurking there.
Perhaps toolkits can adopt a convention that procedure names that start with the characters “Get” use GET, everything else uses POST.
Sounds like a good approach.
Posted by Harry Fuecks atIñtërnâtiônàlizætiøn
This is a test to see if my URIs are encoded correctly. Anne claimed that a URI I had in Hebrew wasn’t properly encoded (in UTF-8), but I’m not even sure how to check. As far as I know I’m doing all my Unicode handling correctly (in UTF-8), but...Excerpt from Keith's Weblog at
One of the problems is that only IE’s and Mozilla’s implementations of xml http request support anything other than GET and POST, it’s a great shame. Safari and Opera have been pushed into implementing the object, it would be great if they gave us the full range of verbs, so we can really do useful stuff without running into these problems.
Posted by Jim Ley at
So I tried submitting a comment...
My browser includes the accept header:
Accept: text/html;application/xhtml+xml;q=0
I get back an application/xhtml+xml resource instead of the text/html one I get instead of the text/html I get if I make the same request without the application/xhtml+xml;q=0. I’m pretty sure this isn’t a spec violation, but it’s certainly not friendly!
Posted by Jim Ley atI remember a talk a few years back by Chris Shiflett at ApacheCon where he was talking about XSS, CSRF, and the like. Chris mentioned that one of the problems was that you could modify resources using GET. Roy Fielding popped up and mentioned that HTTP specifically declares GET (and HEAD) as idempotent. Alas, we’re forced to play in the real world, and it’s too late to shove that cat back into the bag.
Everyone knows that you use GET when you want to create a bookmarkable URL or have a short query string. You use POST when you don’t want people to bookmark the URL or you have lots of data. I feel the historical defaults and limitations of web browsers and servers have already reframed HTTP verbs beyond our control.
Fortunately, there’s no default HTTP method for XMLHTTPRequest, so there’s at least a fighting chance.
Posted by Adam Trachtenberg atShouldn’t the first semicolon be a comma instead? E.g.:
Accept: text/html, application/xhtml+xml;q=0
Posted by M. Brubeck at
Sam Ruby: AJAX Considered Harmful
Sam Ruby has done more careful and detailed analysis of the issues associated with http writes AJAX Considered Harmful.........Excerpt from 42 at
“One of the problems is that only IE’s and Mozilla’s implementations of xml http request support anything other than GET and POST, it’s a great shame. Safari and Opera have been pushed into implementing the object, it would be great if they gave us the full range of verbs”
Safari’s underlying NSURLConnection class incorrectly implements PUT (drops the message body), among other things. This is fixed in Tiger, so maybe Safari 2 will be fixed as well.
Posted by Robert Sayre atJim: Can you provide more information?
$curl -I -H 'Accept: text/html;application/xhtml+xml;q=0' http://www.intertwingly.net/blog/ HTTP/1.1 200 OK Date: Thu, 17 Mar 2005 00:57:29 GMT Server: Apache/2.0.46 (Red Hat) Last-Modified: Thu, 17 Mar 2005 00:56:32 GMT ETag: "354637-5fd8-bb90f000" Accept-Ranges: bytes Content-Length: 24536 Vary: Accept-Encoding,User-Agent X-Pingback: http://intertwingly.net/blog/pingback Content-Type: text/html; charset=utf-8
Adam: while I tend to side with Roy, for the moment, let’s go with your definition. The problem with the current AJAX toolkits is that they don’t allow people to pick the verb, so without them realizing it, they are creating “bookmarkable” URIs for all operations, including unsafe ones.
Robert: Thanks! That would explain it. Unfortunately, the result is still harmful.
Posted by Sam Ruby atSam Ruby: AJAX Considered Harmful
Wayne Burkett : Sam Ruby: AJAX Considered Harmful - "Standardizing improves interoperability, and the reason why I am suggesting UTF-8 is that it is backwards compatible with ASCII, can express the full range of the Unicode character set, and is...Excerpt from HotLinks - Level 1 at
Iñtërnâtiônàlizætiøn
This is a test to see if my URIs are encoded correctly. Anne claimed that a URI I had in Hebrew wasn’t properly encoded (in UTF-8), but I’m not even sure how to check. As far as I know I’m doing all my Unicode handling correctly (in UTF-8), but...Excerpt from Keith's Weblog at
“GET should never be used to initiate another operation which will change state.”
Those are TBL’s personal views. The TAG finding takes a more nuanced stance: “Dereferencing URIs is safe; i.e. agents do not incur obligations by following links.”
This more accurately mirrors the text of RFC2616. It even mentions the possibility of GET-with-body. Something without an obligation: a hit-counter. Maybe. I know you’re familiar with hit-counters that do incur obligations, like those tied to API keys.
Posted by Robert Sayre atRobert, while I definitely agree that there are Shades of Gray involved in the boundary cases, there are clearly cases where HTTP GET should never be used.
Always using POST (like SOAP 1.1 does) may be suboptimal, but using GET for operations like CartModify is wrong.
Posted by Sam Ruby atHere we agree. Someone with a more volatile personality might say “People building toolkits and deploying ‘REST’ systems with things like ‘CartModify’ in the URI have no idea what REST means.”
Posted by Robert Sayre at
Sam Slams SAJAX
“AJAX” is a convenient label for the architecture of applications like Google Maps and Visual Net from Antarctica Systems (which I founded). There’s nothing wrong with the idea. But Sam Ruby spots SAJAX, one of the first toolkits, going horribly off...Excerpt from ongoing at
People building toolkits and deploying ‘REST’ systems with things like ‘CartModify’ in the URI have no idea what REST means.
Posted by MikeD at
A much bigger concern is that unsuspecting grandmothers and bots everywhere can be tricked into modifying online databases simply by following a link.
You don’t have to be clueless to be a victim of this trap. For an attacker it’s as simple as using those URIs as the src attribute in images, oder when referencing them as images in CSS-Stylesheets - you’re browser will issue a GET to that URI and you’ll never even know what hit you...
People who don’t understand this, should google for CSRF (Cross Site Request Forgeries).
Posted by Sencer atSam, It works fine for accessing the site, it is only as a result of the POST when clicking the preview the button after typing the comment, and as M.Brubeck noted there was a typo in my report :
This is the equivalent CURL I believe:
$ curl -D 'headers.txt' -H 'Accept: text/html,application/xhtml+xml;q=0' -d 'parent=1928;title=AJAX%20Considered%20Harmful;Name=Jim;email=jim@jibbering.com;comment=Test;preview=preview' http://www.intertwingly.net/blog/
To which I get back:
HTTP/1.1 200 OK Date: Thu, 17 Mar 2005 08:42:24 GMT Server: Apache/2.0.46 (Red Hat) X-Pingback: http://intertwingly.net/blog/pingback Vary: Accept-Encoding,User-Agent X-Pingback: http://intertwingly.net/blog/pingback Transfer-Encoding: chunked Content-Type: application/xhtml+xml; charset=utf-8
Which is also interesting in that it claims to not vary on Accept:, even though it clearly does.
Jim.
Posted by Jim Ley atSam Ruby's Ajaxian Practices
Sam Ruby has written a couple of practices that we should follow in Ajax applications: Encoding: the data should first be encoded as octets according to the UTF-8 character encoding Idempotency: GET should never be used to initiate another...Excerpt from Ajaxian Blog at
AJAX Considered Harmful: Sam Ruby mit einigen kritischen Worten zu Ajax....
Excerpt from kniebes.net. at
Feedtagger
Feedtagger is an online aggregator, currently early prototype but already showing a great deal of promise. As well as a regular per-feed view, it supports tagging. Remember folksonomies, bit of a craze a week or two ago? That kind of thing. . The...Excerpt from Planet RDF at
Ajax vs. winforms vs. ASP.NET - there is no right answer
”rich” browser applications using CSS, JavaScript and XML (recently termed AJAX applications) seem to be gaining in popularity. Mary-Jo foley has an article on MicrosoftWatch extoling their virtues, an article which sounds...Excerpt from JCooney.NET at
Is there any overhead with a POST compared to a get with XMLHttpRequest? I’ve never really seen an article go into any detail.
Posted by James at
James, from a “bits across the wire” perspective, the primary overhead of POST vs GET is a blank line.
Posted by Sam Ruby at
Sam Ruby on AJAX
Sam Ruby some constructive comments on AJAX. First, use UTF-8 encoding for data. Second, use GET for what its supposed to be used for: getting. These comments are probably more broadly applicable than simple AJAX.......Excerpt from Phil Windley's Technometria at
Good String for i18n testing
Found here: On a somewhat related article... the string is: “Iñtërnâtiônàlizætiøn” URI, it should look like I%C3%B1t%C3%ABrn%C3%A2ti%C3%B4n%C3%A0liz%C3%A6ti%C3%B8n."...Excerpt from batalion.com/thoughts at
Three days worth
Forty five things I wanted to write about, just over the last three days....Excerpt from phil ringnalda dot com at
RESTful coding standards
In AJAX Considered Harmful Sam Ruby starts to lay out a set of useful coding standards for REST. He addresses Encoding and Idempotency, however going a little further has helped me. I have tried to apply the KISS principal and be a minimalist i.e....Excerpt from Fast Takes at
A few comments (after hacking on a “simple” not-unreserved URI character encoder). First of all, you specify the URI escape sequence for `Iñtërnâtiônàlizætiøn` as:
I%C3%B1t%C3%ABrn%C3%A2ti%C3%B4n%C3%A0liz%C3%A6ti%C3%B8n
However, you fail to specify what character encoding you are using. RFC 3986 states that the percent encoded characters of a URI can be in any encoding depending on the application. So it doesn’t make sense to talk about what it would look like as a URI without also indicating that you used UTF-8 to encode it (at least, that’s my best guess). If you used Latin-1 (ISO 8859-1) as a base, then the escaped URI will be:
I%F1t%EBrn%E2ti%F4n%E0liz%E6ti%F8n
I escaped that by hand using an ISO 8859-1 table on the web. If anyone knows the UTF-16 - both little endian and BIG ENDIAN versions, if possible - I would love to know it! I have an idea...
If you are testing Java software to understand `Iñtërnâtiônàlizætiøn`, use this code for the string:
"I\u00F1t\u00EBrn\u00E2ti\u00F4n\u00E0liz\u00E6ti\u00F8n"
If you are testing URI encoding software (like I am right now), append the string " -._~ " to that. You should get the above escaped URI strings with "%20-._~%20" at the end. The "-._~" part are unreserved characters and should be passed through unchanged (along with all alphanumeric characters). The spaces ensure your software parses spaces correctly. Many many many programs incorrectly pass spaces as “ ” or “+” instead of “%20” (which bugs me, since I have a %20 in my URL and nearly everyone’s software drops the % - grrrr).
I hope those tips saves someone the headache I had this weekend!
<i>P.S. SR, your paragraph formatting is odd in Firefox (in the preview at least). Paragraphs containing just the code blocks have little bottom padding.
Guys,
POST support is included in Sajax 0.10 which I have just released. I’ve also posted a topic on the message board to help people understand when POST should be used instead of GET. I welcome other suggestions regarding Sajax and its standard compliance.
- Thomas Lackner, author of Sajax
Posted by Thomas Lackner atAJAX (2)
Sam Ruby has started to write about AJAX best practices. A comment in one of his posts referred to a del.icio.us AJAX list which provided a pointer to the Ajaxian blog, which has a good amount of useful info about JavaScript libraries and more....Excerpt from Muddy clouds at
Ajax? asynchronous JavaScript and XML
Well it looks like theres some push behind the AJAX naming now. I believe it stands for Asynchronous JavaScript and XML and translates into this easy to understand list. standards-based presentation using XHTML and Cascading Style Sheets (CSS);...Excerpt from cubicgarden.com... at
<blockquote>If you are testing URI encoding software (like I am right now), append the string “ -._~ ” to that. You should get the above escaped URI strings with “%20-._~%20” at the end. The “-._~” part are unreserved characters and should be passed through unchanged (along with all alphanumeric characters).</blockquote>
The list of unreserved characters includes <code>-_.!~*'()</code>, in addition to the alphanumerics.
Posted by Porges atSajax Still UnSafe
This is apparently “per [my] suggestions”. [Via Tim Bray] Looking at the code, SAJAX Version 0.10 now supports GET and POST interchangeably. While this does have the desired affect of allowing requests of virtually any size, it does not... [more]Trackback from Sam Ruby at
First of all, blockquote requires a block-level element inside of it for valid HTML.
The list of unreserved characters includes
-_.!~*'(), in addition to the alphanumerics.
Which spec is that from? unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" The !*() characters are sub-delims.
^I see - that’s from the previous RFC for URI syntax. Which one should I follow?
Posted by Jimmy Cerra at
Oops :)
Well 3986 marks 2396 as obsolete, so you’re right - although many applications don’t escape any of !*'().
Posted by Porges atMisunderstanding REST: A look at the Bloglines, del.icio.us and Flickr APIs
I’ve slowly been appreciating the wisdom in using REpresentational State Transfer (REST) as the architectural style for building services on the Web. My most recent influences have been Nelson Minar’s ETech presentation entitled Building a New Web...Excerpt from Dare Obasanjo aka Carnage4Life at
Smart web clients; Ajax way..
We have been hearing a lot about Ajax (asynchronous JavaScript and XML) these days. It is for sure changing the way web clients are presented. Why go far; Google maps (so called poster child for Ajax) /Google Suggest are the few ones to implement...Excerpt from Rajesh about Prodigious revolution of Tech Life at
Ajax? asynchronous JavaScript and XML better known as Remote Scripting
Well it looks like theres some push behind the AJAX naming now. I believe it stands for Asynchronous JavaScript and XML and translates into this easy to understand list. standards-based presentation using XHTML and Cascading Style Sheets (CSS);...Excerpt from cubicgarden.com... at
HTTP GET is an Attractive Nuisance
Paraphrasing Sam Ruby: Jon Udell: HTTP toolkits make it easy to do the wrong thing, hard to do the right thing. Dare Obasanjo: del.icio.us, flickr, and Bloglines use GET for edit resources. Sam Ruby: AJAX toolkits must beware of how they use GET....Excerpt from More Like This WebLog at
Sam Ruby: AJAX Considered Harmful: "Looking into t...
Sam Ruby: AJAX Considered Harmful: “Looking into the current PHP implementation of SAJAX, you will see the following:...”...Excerpt from Random Notes & Bookmarks at
The wrong end of the telescope?
Leigh Dodds, Mark Nottingham, and Ryan Tomayko have all suggested that, while client-side HTTP toolkits may contribute to HTTP abuse, server-side frameworks are more fundamentally to blame. Sam Ruby made a similar point in his post-ETech critique...Excerpt from Jon's Radio at
Yes AJAX is probably harmful if you use primative technologies like PHP.
PHP ridden pages are harmful in their own respect ;)
On the otherhand with jsonrpc and cherrypy the server knows which request are jsonrpc request and which ones are normal request.
;)
Posted by nopa90 atYou were warned.
Read AJAX Considered Harmful. Read it very carefully. Read whenToUseGet. Read it very carefully. People get uptight about GET for...... [more]Trackback from franklinmint.fm at
Google Web Accelerator not ready for prime time
I uninstalled the Google Web Accelerator this morning after reading that it has some serious bugs that compromise users' logins to sites that use cookies for authentication. Basically, the proxies that the Google Web Accelerator connects to are not...Excerpt from rc3.org Daily at
Backpack, Google Accelerator, HTTP
As often happens, Sam Ruby saved me from wasting too much time idly browsing the web (no energy to work on more important stuff on Friday night) with his latest post: This Stuff Matters. Sam links to a post by Robert Sayre on the Google Accelerator...Excerpt from Ludo at
Google vs. Rails
Interesting to see what happens when two “well-liked” communities clash. Background: Google released a web accelerator, which follows the HTTP specs (AFAICT), but wreaks havoc with a category of Web 2.0-style apps which, for convenience, ignored the...Excerpt from david ascher at
“Considered Harmful” Considered Harmful
Ever since the sixties, there has been a long-standing tradition of criticizing something well established by stating that it’s considered harmful—starting with the famous Go To Statement Considered Harmful paper from 1968 which pushed...Excerpt from Pretty in Punk at
AJAX
Hace dos semanas escuché por primera vez via PC++ la palabra AJAX. AJAX son las iniciales de Asynchronous JavaScript and XML, una técnica del desarrollo web para crear aplicaciones interactivas: GMail debe ser el ejemplo que todos conocemos.Como en...Excerpt from La última curda at
Ajax, un problème ?
Ajax, un problème ? Sam Ruby explique deux problèmes possibles d’Ajax : idempotence codage des caractères ajax, XMLHttpRequest [link]...Excerpt from Karl & Cow - Le carnet Web at
Simple AJAX Code-Kit (SACK)
In this seemingly unlimited stream of AJAX articles and frameworks, let me present you to SACK. SACK is a light-weight AJAX API, written by Gregory Wild-Smith. Gregory writes: "I’ve seen AJAX solutions like SAJAX or Dojo, and they haven’t really...Excerpt from Warping it up! at
Scrubbing bubbles and other cures for the common thin client application
My professional has a strong affinity with jargon and acronymns; so, it came as no surprise to me when “AJAX” was coined not too long ago by Adaptive Path. However, in the end I’m all the more convinced that AJAX, as with most technologies in the...Excerpt from Craig's Musings at
AJAX, fashion, Google Maps and Flickr
AJAX (Asynchronous Javascript And XML) seems to be flavour of the month. First noticed in a mainstream online application on Flickr, subsequently on Google Maps and on the still (for me) mysterious Ruby on Rails....Excerpt from cloudsoup weblog at
Enhancing User Experience to Affect the Bottomline
AJAX is having a tremendous effect on web developers (and website visitors). There have been excellent examples of it’s use popping up all over the web, along with warnings about best practices of using AJAX. Paul Scrivens points out that...Excerpt from Brian Sweeting at
How to ReSTfully Ajax
Here are some pointers for learning more about the Ajax programming model and how to properly design your Ajax application : Ajax is said to be the cross-platform successor to Java... huh... (David, thank you for this pointer) Ajax should be...Excerpt from AkaSig at
blogger import
Notify Blogger about objectionable content.What does this mean? [link] ——– AUTHOR: Random Stuffer DATE: 11/13/2005 06:44:48 PM —– BODY: CEO Book——– AUTHOR: Random...Excerpt from quarter-random stuff at
Backpack, Google Accelerator, HTTP
As often happens, Sam Ruby saved me from wasting too much time idly browsing the web (no energy to work on more important stuff on Friday night) with his latest post: This Stuff Matters. Sam links to a post by Robert Sayre on the Google Accelerator...Excerpt from Ludoo at
Atlas and Ajax-based APIs are really hard to maintain, and its client side architecture breaks server-side API.
zumiPage for ASP.NET is a better solution.
[link]
Posted by Amir Leshem at
REST and Web Services links
I’ve been doing some research into REST and web services. Here’s some links I found helpful. Paul Prescod: Common REST Mistakes (Date unknown) Sam Ruby: Shades of Grey (Sept 2002) Sam Ruby: Vacant Space (Sep 2004) Mark Pilgrim: RESTagra (Sep 2004)...Excerpt from Just Looking at
Sam Ruby: AJAX Considered Harmful
Someone at Smarking has bookmarked your post.... [more]Trackback from Smarking at
I’ve found that you can’t set an element’s innerHTML from Ajax with UTF-8 encoded html. You get a bunch of circumflexed As (\xC2 or â) next to normal entities like . The way around this is to UTF-8 decode the html first:
function decode_utf8( s )
{
return decodeURIComponent( escape( s ) );
}
(from [link])
Shane
Posted by Shane atSam Ruby: AJAX Considered Harmful
The bad things about AJAX...Excerpt from Public marks with tags harmful & javascript at
Backpack, Google Accelerator, HTTP
As often happens, Sam Ruby saved me from wasting too much time idly browsing the web (no energy to work on more important stuff on Friday night) with his latest post: This Stuff Matters. Sam links to a post by Robert Sayre on the Google Accelerator...Excerpt from Ludo at
Sam Ruby: AJAX Considered Harmful
be sure to encode your apps correctly!...Excerpt from del.icio.us/tag/ajax at