Please read my blog's comment policy here.
From time-to-time, web developers contact the IE team reporting that they’ve encountered a problem whereby Internet Explorer submits a POST but fails to transmit the content body. This bodyless POST indicates via the Content-Length header that the POST is zero-bytes long, regardless of how much data was supposed to be uploaded.
This behavior occurs on servers that use challenge-response authentication protocols like NTLM or Kerberos/Negotiate. For performance reasons, Internet Explorer does not immediately transmit a POST body if it expects to immediately receive a HTTP/401 response with a challenge for credentials. Without this optimization, IE would be forced to reupload the (potentially large) POST body multiple times, wasting bandwidth.
The obvious question: What leads IE to expect a credential challenge?
IE expects a credential challenge if it has previously received a credential challenge from within the protection space. Put simply, a protection space is the origin+current folder path and any paths beneath it.
Consider the following example:
In this case, the first two folders challenge the client for a username and password, while the public folder does not.
After the first credential challenge from the privateupload folder, the next time the client submits a POST to that folder or the admin folder beneath it, the POST will be zero-bytes in length. If the server returns a 401 as expected, the client will respond to the challenge and eventually upload the entire POST-body. If, however, the server does not return a 401 response, the client will simply submit the single zero-byte post, which likely will lead to an error message or a corrupted file on the server.
In the configuration above, the user will encounter a problem if he submits a bodyless POST to /publicupload/; since no credential challenge will be forthcoming, the upload will fail.
What might unexpectedly trigger the bodyless POST optimization? Most common cases are due to server configuration errors. For instance, if the user visits http://example.com/privateupload (without the trailing slash), the server might mistakenly return a 401 first, instead of immediately returning a 301 to /privateupload/. If this happens, the protection space will be considered to be the root folder http://example.com/*, causing all POSTs to any path anywhere on the server to trigger the bodyless POST optimization.
A similar problem occurs when the user never directly visits a page within the root folder, but a page within a subfolder issued a request to the root that resulted in an authentication challenge. A common case is the download of FavIcon.ico, for instance.
To avoid problems with the bodyless POST optimization, ensure that either all paths are configured to require authentication, or that only very specific subpaths require credentials and that all files within the protection space are configured to require authentication.
Until next time,
Very informative. Thanks. Does .net implementation of HTTP protocol exhibits the same behavior? Because recently in our company proxy authentication mechanism has been changed. Upon investigation with fiddle(btw thaks for it) and wireshark, we determined that client is sending 0 length requests after the first request which are allowed to pass through the proxy. Because there is no content third party service is throwing exceptions. Could you suggest any work around?
@shiva: I would not be surprised to learn that .NET's implementation behaves the same way for the same reason (also for performance).
One simple way to check would be to configure Fiddler to do authentication for you instead of having the client do it. (See the comments about X-AutoAuth here blogs.msdn.com/.../using-reflection-to-get-ntlm-negotiate-challenge-response-string-without-sending-request-using-webrequest-object.aspx)
We are also facing this issue , our backend is in Java and we use sso (LDAP) based authentication, we face this issue intermittently for Ajax POST , Form Submit(POST) , kindly let us know if any solution .
Thanks in advance,
Hi Eric, Not sure if you still respond to comments on this blog, but I had a question about IE "protection spaces". You say they made up of the origin and current folder. What do you mean by "origin" in this case? The origin in IE's "same origin policy" does not include port. However, in my testing with two IIS sites that differ only by port, I am unable to reproduce the zero-length post problem. When all my content is in one IIS site (some using integrated authentication and some using forms authentication), I can reproduce the problem consistently.
So, does "origin" in terms of IE protection spaces include the port?
EricLaw [MSFT]: Robert: That's a very interesting finding. I wouldn't expect the port to matter in this case, but it's entirely possible that the comparison logic used down in WinINET is using the port rather than the Zone (since WinINET doesn't have much interaction / knowledge of URLMon's Origin rules). The fact that a request on a different port necessarily MUST be sent on a different connection may be relevant here.
hi, I have a problem with IE and NTLM authentication. The POST values are not coming in PHP. we did the following configurations as follows,
AuthType NTLMNTLMAuth onNTLMAuthoritative onNTLMDomain ASCORPNTLMServer nav8adasnp04.ascorp.comNTLMBackup nav8adasnp03.ascorp.com
[EricLaw] Have you actually watched what's coming over the network using Fiddler or Wireshark? Do you have a capture file you could send me?
So is Microsoft ever going to fix this? Interestingly, we used to face this problem with IE6 three to four years ago, but as out organization migrated to IE8, the problem went away. Now we are migrating to IE10, and the problem is back again.
In our case, the issue manifests somewhat differently. If a page request after a NTLM negotiate returns client side artifacts, a subsequent POST request will contain an unsolicited NTLM response header. IE includes the header and a Zero Content length header even though the browser was not solicited with a WWW-negotiate header from the server.
[EricLaw] Sorry, you haven't provided enough details to help; claims like: "The request contains a response header" are very ambiguous. Please feel to contact me by email. Thanks!