Friday, May 18, 2007

GET vs. POST - Save your users!

This is one thing I've seen gotten so wrong so often and resulted, I felt compelled to put some of my thoughts on the subject down here.

First, a little explanation. GET and POST are commands issued to a web server. Your browser uses the commands to request a web page, and provide information to a web application.

In the case of GET, this is often done via a specially formatted query string. The text and information of this query string is visible to the user assuming your application resides in a normal browser window and not one where the address has been hidden from view.
GET can be used as a method for sending form data, and it is used often in the case of Search Engines. Simply search for "dog" on Google and you'll find this URL:

http://www.google.com/search?source=ig&hl=en&q=dog&btnG=Google+Search

GET is convenient. As you can see from the above URL, I could just as easily encode a link like this and you'd be sent away from my blog to a search about a dog. In fact every link that goes to a web page is a GET operation, not just forms like Google's Search form that use the method GET.

POST is a method that is primarily designed for sending form data (it can be used in many other ways, but we'll skip those for now). POST data does not appear in the address bar like GET data. It also cannot easily be encoded into a link.

So which should I use and when?

The answer is simple, but the solution is sometimes painful. GET should be used only when the operation it is performing is considered safe. Safe means an operation that is looking up data. I've even heard it said an operation that "asks a question", or "navigates somewhere". In the case of a search engine, you're asking a question. In the case of a link, you're navigating somewhere.

What's more important is knowing when GET should not be used.

Rule #1: Never use GET in a login form or to send sensitive data
I know that this should be obvious, but I've seen it before. For those who are still scratching their heads. When you use GET in a login form, the user ID and password of the logged in user will appear in the address bar. This is called exposure. :-)
I've seen plenty of older e-commerce sites that send credit card data this way. This is "bad" on more levels than I can get into here. Just don't do it.

Rule #2: Don't use GET for any operation that modifies something.
This is where most people fail. I've logged into my banking site, and I'm looking at my account. Next to my account is a link that says "Delete". It links to the following URL:

https://www.mynicebank.com/accountOperations.aspx?Action=Delete

My, how convenient is that to code? No form necessary, no javascript, no buttons, no hidden values, just an anchor reference. That's also leaner HTML.

Technically it works. Since I'm logged in and have an authenticated, encrypted session, it's thought to be secure (assuming your account number isn't in that querystring, it might actually be secure).

Unfortunately, some browser extensions and some alternative browsers do something called "Look Ahead". And it does exactly what it sounds like. It looks at the page you're on, and pre-loads all of the links on the page, figuring that you're probably going to click on one of them. The idea is that if the browser pre-loads all of the links, and you click one, it'll already be in your cache and navigation will run lightning fast. Unfortunately, the Look Ahead doesn't know anything about what the link actually does.

If mynicebank.com encoded the delete link that way, and I was running FasterFox, my bank account might be gone lightning fast even though I never clicked the link.

Rule #3: Never use GET to send large amounts of data
This is less of a rule and more of a suggestion. Some older web servers and browsers limited the length of a GET request. Most, nowadays, don't. I've even seen some clever hacks that use TinyURL to store entire files.

While writing this, I discovered a great resource over at the w3c. If you're still curious, check it out. Those guys are a lot smarter than me and probably came up with something I missed.

No comments: