views:

434

answers:

3

When I use Google Chrome to make an AJAX POST request I get extra empty parameter "_" on server-side.

Here's some background information:

For example simple:

>>print sorted(request.POST.keys())
['_','my_parameter']

I've Googled and I found few posts in mailing lists mentioning the same problem but I couldn't find an answer why is that happening. There were people reporting same issue using PHP and Safari so I don't think it's Server/Back-end related. I tested the same page with Firefox and I didn't get the extra parameter.

I've checked HTTP 1.1 specification and couldn't find anything related.

The strange thing is that I have never noticed this behaviour before.

I haven't written a separate test to test it on all modern browsers yet, I though I'd ask here first. I expect the same problem might happen with Safari.


A small side question; is it bad practice to expect that browser will only post the parameters which I expect or there's a chance that browser will post unnecessary/unexpected parameters like in this case.


Answer

As Blixt suggested the problem was in Prototype:

if (params = Object.toQueryString(params)) {
  if (this.method == 'get')
    this.url += (this.url.include('?') ? '&' : '?') + params;
  else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
    params += '&_=';
}

Found it in bug tracker as well. Looks like this is fixed on Safari side, but it still in prototype code as workaround.

+2  A: 

Please use Fiddler, to trace the HTTP traffic between your Chrome browser and the server. Do you find the additional paramter in the HTTP request?

mkoeller
Unfortunately I can't do that at the moment, but I'm quite sure it's not originating in web-server.
Maiku Mori
I wrote a small test which should act the same as the request in my web application. The extra parameter also shows up in fiddler so as I expected it's not server-side issue.
Maiku Mori
+2  A: 

Most likely, the empty parameter is from your JavaScript framework. Usually, frameworks add an additional parameter (to make a URL unique) to prevent certain browsers (in other words, Internet Explorer) from caching a request.

I have never experienced any browser adding additional query parameters on their own accord.

Blixt
It's a POST request, it should never be cached according to HTTP specification, also it didn't happen in FireFox. I'll go over Prototype source just in case.
Maiku Mori
Well, you know... Browsers and specifications... `=)` If you have the page public on the internet, it'd be easy for me to check where the `_` comes from.
Blixt
Yep, I tried with raw XMLHttpRequest() and it didn't send the parameter. Updated question with more info.
Maiku Mori
+1  A: 

To answer this:

A small side question; is it bad practice to expect that browser will only post the parameters which I expect or there's a chance that browser will post unnecessary/unexpected parameters like in this case.

It is a bad idea to trust input coming from an untrusted source, and a user agent on the Internet is an untrusted source.

You should assume you can receive:

  • parameters that you expect with values that you expect
  • parameters that you expect with values that you don't expect
  • parameters that you don't expect with values that you don't expect

You should also assume that you may not receive the parameters you expect.

Grant Wagner
I understand that anyone can fabricate a request, question is more like can I trust browser to send only my parameters when legimite request is made. It boils down to: Can I use if len(request.POST) == MY_EXPECTED_PARAM_COUNT: #do my stuff
Maiku Mori
@Maiku: I guess you want to use that count as a validation fail-fast? I would rather validate each POST value and fail as soon as one falls outside the expected range of values, or doesn't match an expected data type rather than relying on a count of incoming POST values that you've discovered can be inaccurate. I also see using that count as a bit of a brittle design. Say you add a new POST value to your Ajax as part of other changes. You've now tied your server component to those changes, you can't deploy Ajax that POSTs an extra unused value until you change your server-side code.
Grant Wagner