8

I am building some ajax in a Perl web framework Dancer I am not sure it is responding with proper http headers as I cannot trigger jQuery's ajax success handlers from what appear to be otherwise successful requests. Using the ajax snippet below I get the following output in a browser console. The complete callback gets called successfully and gives what looks like successful output. Status:200 StatusText:"OK" However the success handlers never get called.

$.ajax({type: "GET", url: "/learn/faq",
 success: function(data){console.log('omg got it');},
 complete: function(data){console.log("complete", data);}
}).success(function(data){console.log('defered');});


Object
XHR finished loading: "https://www.localhost:4443/learn/faq". assets-d36e1bb9fd59ba3dbd0f8a0cbb37ed8e.js:1
complete 
Object {readyState: 4, responseText: "↵↵<!DOCTYPE html>↵<html xmlns="http://www.w3.org/1…ead/conversion.js"></script>↵↵↵↵</body>↵</html>↵↵", status: 200, statusText: "OK"

I should be seeing the omg got it and defered messages but am not. Looking at this I feel there is more to the jQuery success handler than the status and Dancer http implementation is not responding correctly.

Further more I have since added an error handler to the snippet and the error handler is getting triggered with what looks like a successful request.

$.ajax({type: "GET", url: "/learn/faq",
 success: function(data){console.log('omg got it');},
 complete: function(data){console.log("complete", data);},
error: function(data){console.log("error!", data);}
}).success(function(data){console.log('defered');});
Object
XHR finished loading: "https://www.localhost:4443/learn/faq". assets-8cd028b93e0db9dd9455125dc98d5ae1.js:1
error! 
Object {readyState: 4, responseText: "↵↵↵↵↵↵↵↵↵↵↵↵↵↵↵↵<!DOCTYPE html>↵<html xmlns="http:…></script>↵↵↵↵</body>↵</html>↵↵↵↵</body>↵</html>↵", status: 200, statusText: "OK"}
complete 
Object {readyState: 4, responseText: "↵↵↵↵↵↵↵↵↵↵↵↵↵↵↵↵<!DOCTYPE html>↵<html xmlns="http:…></script>↵↵↵↵</body>↵</html>↵↵↵↵</body>↵</html>↵", status: 200, statusText: "OK"}

Here are the response headers from jQuery getAllResponseHeaders()

complete Date: Tue, 01 Jan 2013 22:43:52 GMT
Content-Encoding: gzip
X-Powered-By: Perl Dancer 1.3095.1
Transfer-Encoding: chunked
Connection: keep-alive
Server: nginx/1.2.4
Strict-Transport-Security: max-age=2592000
Content-Type: text/xml; charset=utf-8
kevzettler
  • 4,783
  • 15
  • 58
  • 103
  • You're saying you're not seeing `omg got it` or not seeing `defered` (or both?). Because [when I do it](http://jsbin.com/uzekac/1) I get `omg got it` followed by `defered` followed by `complete`. – T.J. Crowder Jan 01 '13 at 22:20
  • Not seeing either of those success messages. If I run the same jQuery snippet on a multitude of other sites online they are triggered. – kevzettler Jan 01 '13 at 22:22
  • @ kevzettler: So the question is: What's so special? Have you really copied-and-pasted the code in your question? You're not really doing cross-origin stuff, etc.? There isn't a script error elsewhere on the page obscuring the result? There must be something, the basic answer is that jQuery's `success` is triggered by a `200` response that it's able to successfully deserialize according to the `Content-Type` header (or the `dataType`, if you provide one, but you aren't). – T.J. Crowder Jan 01 '13 at 22:24
  • What you're quoting doesn't add up. You're quoting `$.ajax(... url: "/learn/faq"` but then showing that what you're getting back is `XHR finished loading: "https://www.crowdtilt.com/"`. That's a mismatch. Please quote what you're **actually** doing and what you're **actually** getting back. – T.J. Crowder Jan 01 '13 at 22:31
  • @T.J.Crowder This is the exact copy-pasted code I am testing with. I noticed this issue in other areas of the project and isolated it to this. I have reproduced the issue with this snippet on our production app which is on a real SSL cert and everything same origin domain. As you've already shown if I take the snippet other sites it behaves normally. My last update to the question shows that instead it is triggering the `error` callback which might be a better point to investigate. – kevzettler Jan 01 '13 at 22:34
  • @ kevzettler: You've **changed** what you've posted for the part that I was talking about. Don't try to claim it wasn't mis-matched before, that's just a waste of everyone's time. At least what's there now matches up (or *seems* to). – T.J. Crowder Jan 01 '13 at 22:36

2 Answers2

13

The success handler will be triggered if

  • The response has HTTP status code 200 (yours does)
  • jQuery is able to deserialize the response according to the Content-Type header in the response (or the dataType option, if you provide it, which overrides the Content-Type header)

So for instance, if your response had a Content-Type header of application/json or application/xml, the response you've quoted won't trigger the success handler because it cannot be successfully deserialized as either JSON or XML.


Your latest edit (as of this writing) reveals the problem:

Here are the response headers from jQuery getAllResponseHeaders()

...

Content-Type: text/xml; charset=utf-8

I suspect your response isn't valid XML, so jQuery can't deserialize it as XML, so it's failing.

Community
  • 1
  • 1
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
0

To expand on TJ's answer, the following is an excerpt from the jQuery 3.5.1 (Same check is in 1.7.1 version as well so it's safe to assume the versions in-between does the same) .

   // Determine if successful
   isSuccess = status >= 200 && status < 300 || status === 304;

As per it, status code for success is not just 200 but anything between 200 and 299 and 304.

Starx
  • 77,474
  • 47
  • 185
  • 261