11

I have a site that I enter a username/password and click a login button. The login button makes an XMLHttpRequest object, and fires it off.

On Chrome, Firefox, Opera, Safari, Android devices, iOS devices this works fine. IE9 will work fin so long as I am on an HTTP address and not using HTTPS.

On HTTPS, IE9 behaves as follows:

The first login request never returns anything back. The F12 screen does show my login request in the network tab and all looks correct. The scripting tab never throws an error. Simply nothing happens.

Here's the crazy part: - If I click login a second time, it actually works. - If I click refresh on the browser, and then login, that will work as well!

I am making the request as follows:

   var x = new XMLHttpRequest();
   x.open("POST", "/Relative/URL/Path", true);
   x.setRequestHeader("Content-Type", "text/plain");
   x.onreadystatechange = function () {
      if ((x.readyState == 4) && (x.status == 200)) {
            // handle callback
      }
   }
   x.send(my request);

When this fails, the debugger will go from the x.send() line into the onreadystatechange code. The readyState will be 1. This will be the last I can debug because nothing else happens.

Any ideas would be extremely appreciated.

[EDIT]: I let one request go to see what would happen. The onreadystatechange event fired again with readyState = 4 and status = 12152. The network view in IE9's F12 screen shows the result as Aborted and the time taken as 1589.07s. A Google search shows this means the connection was closed on the server.

[EDIT 2]: Based on a comment below I redid this code to just use jQuery's ajax() method. I thought this might have a chance at eliminating bad code on my part. No such luck. The same behavior occurs.

   $.ajax({
      "url": sUrl,
      "success": function (data, textStatus, x) {
         workerCallback(data, id, "");
      },
      "error": function (x, testStatus, errorThrown) {
         workerCallback("nc", id, errorThrown);
      },
      "contentType": "text/plain",
      "data": JSON.stringify(req),
      "dataType": "json",
      "timeout": 1600000,
      "type": "POST"
   });

[FINAL UPDATE:] I've updated the code. If a timeout occurs, I simply repost the same request - one time only. Quite the hack but it works. Unless anyone finds the solution I'll split the bounty between a few helpful ideas people have had below.

Paul Sweatte
  • 24,148
  • 7
  • 127
  • 265
Paul
  • 5,700
  • 5
  • 43
  • 67
  • Is cache clean? Did you use anything like Fiddler to see if requests go out? – epascarello Oct 01 '12 at 13:01
  • The cache is clean. Great suggestion on monitoring the requests. I opened WireShark (network sniffer) and checked. I can't see anything going out when I click login the first time. The second time I do see the requests! But IE says it made the request?! – Paul Oct 01 '12 at 13:20
  • Look up the error code: http://support.microsoft.com/kb/193625 – epascarello Oct 01 '12 at 13:31
  • Have you tried to wrap your code in a function and call it after the document is ready: `window.onload = function() {...}` – thobens Oct 01 '12 at 13:53
  • Same issue, however that suggestion did help. When I opened the page for the first time the login request hung forever again. When I clicked refresh it all worked fine (save exact behavior as the button). I did get an error message this time in the console: SEC7111: HTTPS security is compromised by https://[mysite]/waiting.gif. The URL I navigated to is already HTTPS. The HTML points to this GIF as a relative URL, not an absolute. Not sure why this would be or if it is related. – Paul Oct 01 '12 at 14:15
  • I wonder what would happen if you tried the POST with jQuery. Maybe there is a missing shim for that browser that you need. If jQuery works fine, this may be an indicator to the problem. Hope that helps. – Nash Worth Oct 07 '12 at 00:00
  • ClintNash - I redid the code to use jQuery.ajax(). It does the exact same thing. This really seems to confirm to me that the bug may be on the server side, but I still need to know what is wrong in order to tell the server guy what to fix on his end. Updated code using jQuery is in place at the same location now. – Paul Oct 08 '12 at 15:13
  • I have exact same kind of form all, everything works well, but all my urls are on the same domain. For cross domain, XMLhttpaRequest will request options for allow origin. May be that is what your server isn't processing. Definitely something is wrong on server side. – Akash Kava Oct 09 '12 at 04:32
  • @Paul Doesn't that exactly mean the opposite -- that the problem isn't serverside? – Markus Unterwaditzer Oct 09 '12 at 11:37
  • My URLs are on the same domain as well. It's not cross-domain. – Paul Oct 09 '12 at 13:00

3 Answers3

1

This seems like a strange issue and it's hard to test it without poking around the code on an https site.

If you want a quick fix you could try doing an initial (dummy) request then abort it right away with a short setTimeout and make a second (real) request.

As per your description it should work.

gblazex
  • 49,155
  • 12
  • 98
  • 91
  • You can poke around the code. I posted all of it in the link in the bounty description. – Paul Oct 08 '12 at 12:34
  • Although this is quite the hack, I updated the code based on your comment and one other. Now if a timeout occurs, I repost the request - one time only. So IE now gets a nice long delay logging in, however it will work in the end. If no one has an exact answer, I will split the bounty up between you and one other. – Paul Oct 08 '12 at 16:23
  • Yes but I don't have an https server to test it. You don't have to give IE a long delay. Abort a quick request first and do another one right away, and it should be fast everywhere. – gblazex Oct 09 '12 at 22:28
  • @galambalazs Thanks. Here's an [https server](https://code.google.com/apis/ajax/playground/) – Paul Sweatte Oct 10 '12 at 00:48
  • @galambalazs You are correct on the delay. I changed it so that only the initial login request will repost, and only after a few second timeout, and only one time. This effectively solves the issue although it's a hack! – Paul Oct 10 '12 at 12:49
0

during debug on the first request this came through

enter image description here

There is a related post to this exact error... IE 9 Javascript error c00c023f

The author put the following in the onreadystatechange handler

if (xmlHttpRequest.aborted==true) { 
  stopLoadAnimation();
  return;
}

This may help point you in the right direction.

Community
  • 1
  • 1
DRobertE
  • 3,478
  • 3
  • 26
  • 43
  • Thanks for looking, however that error is not actually an error. You've debugged into the first time the readyState is set. In this case it's set to 1 because it's about to make the call. The status property will not be set yet thus attempting to view that in the debugger will error. My code checks for ready state and only then access status and does not throw an error. – Paul Oct 04 '12 at 19:19
0
  • Timeouts prevents the request from being terminated at readyState 1, and it succeeds afterwards due to content sniffing.

  • Configure SSL client authentication on the login form using the web server config

  • Insert a hidden element (such as an image) that references an URL that requires SSL client authentication

  • Use a protocol relative gif hyperlink, such as //example.com/image.gif, to avoid the SEC7111 mixed content vulnerability

  • The URL of the open method matches the domain when using HTTP, but not HTTPS, which causes the request to fail, but subsequent requests fallback to the security zone policy

  • Use a comparison between window.location.protocol and document.location.protocol to check whether the script is executing in the same context as the page

  • Sending JSON as MIME type text/plain may trigger content sniffing

  • Compare the Accept header between the requests that fail versus those that succeed

  • HTTPS Caching may be an issue

  • The Connection header may need to be set

  • Proxy configuration may be an issue

  • The initial header response values may be too large (e.g. HTTP status description has a limit of 512 characters)

  • document.readystate may not be complete on the initial request, which causes premature execution problems

  • Certificate revocation checks may block the initial JSON POST, but allow subsequent requests after the GET callback

  • readyState and status properties should be referenced using the callback scope rather than the variable x to avoid using the closure scope:


    function cb()
      {
      if ( (this.readyState === 4) && (this.status === 200) ) 
        {
        // handle callback
        }
      }

    onreadystatechange = cb;
Community
  • 1
  • 1
Paul Sweatte
  • 24,148
  • 7
  • 127
  • 265
  • - I am already using a relative hyperlink. I only got the gif issue the one time. - The open URL is relative, so it must match the https domain. I've also used the full URL pointing to https and it still fails. - When it fails, document.location.protocol and window.location.protocal match perfectly as https:. - I tried sending as "application/json" but this had no affect. - Once I switched the code to $.ajax(), there was no reference of 'x' needed to be switched to 'this'. I switched this the other day. – Paul Oct 09 '12 at 22:09
  • @Paul Sweatte - switching `x` to `this` won't change a thing because they refer to the same thing. There's no hoisting going on here because it's a *`FunctionExpression`* not a *`FunctionDeclaration`*, I don't think you have the slightest idea what you're talking about. See: http://kangax.github.com/nfe/ – gblazex Oct 09 '12 at 22:22
  • Is the submit button inside a form element? If so, there may be a [race condition](http://stackoverflow.com/questions/11449515/) or a problematic [action attribute](http://stackoverflow.com/questions/1131781/). – Paul Sweatte Oct 09 '12 at 22:40
  • The submit button is an anchor tag that is styled. There are no form elements. – Paul Oct 10 '12 at 12:47
  • Check the [Accept header](http://stackoverflow.com/questions/3781343/jquerys-getjson-not-setting-accept-header-correctly), [mixed content](http://blogs.msdn.com/b/ieinternals/archive/2009/06/22/https-mixed-content-in-ie8.aspx), [cross-domain limitations](http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx). Check [browser settings](http://msdn.microsoft.com/en-us/library/ee264315) and use [Fiddler](http://fiddler.wikidot.com/debugmixedcontent) to troubleshoot. – Paul Sweatte Oct 10 '12 at 19:25