[FYI] MSXML HTTP translates response status code 204 to 1223

  • Thread starter Thomas 'PointedEars' Lahn
  • Start date
T

Thomas 'PointedEars' Lahn

Hello,

I do not know if this is really news to you, but since I have encountered
it not before today in one of my commercial projects (XHR had not been a
priority there), and a Google Groups search here for "1223" returned it only
once in a rather long posting of Conrad Lender that advocates browser
sniffing to deal with this kind of problem[1], I thought I could as well
tell you about it.

In a nutshell:

As described e.g. in [2], contrary to the MSDN Library documentation[3], the
IXMLHTTPRequest implementation in MSXML HTTP (at least in IE 8.0 on Windows
XP SP3+) does not handle HTTP responses with status code 204 (No Content)
properly; the `status' property has the value 1223 then (which I found out
thanks to IE 8.0's built-in debugger). The used ActiveX/COM ProgID to
reproduce the bug was "Microsoft.XMLHTTP" which should select MSXML 3.0 or
earlier (AFAIK).[4]

As a result, I have changed

status: {
OK_EXPR: /\b(0|2\d\d)\b/,

// ...
}

into

status: {
/*
* NOTE: MSXML translates 204 to 1223, see
* https://prototype.lighthouseapp.com/projects/[...]
*/
OK_EXPR: /\b(0|2\d\d|1223)\b/,

// ...
}

in my httprequest.js (yet to be officially released). (See, no browser
sniffing! :))


HTH

PointedEars
___________
[1] <[2]
<http://forumsblogswikis.com/2008/07/02/ie7-xmlhttprequest-and-1223-status-code/>,
[3] <http://msdn.microsoft.com/en-us/library/ms767625(VS.85).aspx>
[4] <http://msdn.microsoft.com/en-us/library/6958xykx(VS.80).aspx>
 
T

Thomas 'PointedEars' Lahn

Stefan said:
Thomas said:
status: {
/*
* NOTE: MSXML translates 204 to 1223, see
* https://prototype.lighthouseapp.com/projects/[...]
*/
OK_EXPR: /\b(0|2\d\d|1223)\b/,

// ...
}

Yes, this rings a bell. I must have run into the same thing, because the
code I (re)use for XHR related tasks has this function:

function httpStatusOk (status) {
return (status >= 200 && status < 300 // 200-299: HTTP OK range
|| status == 304 // HTTP Not Modified
|| status == 1123 // MSIE Bug (should be 204)
^^^^
Is this a copypaste error or am I seeing a bug here? Should be _1223_.
Thanks for the links.

You're welcome.


PointedEars
 
T

Thomas 'PointedEars' Lahn

kangax said:
Thomas said:
I do not know if this is really news to you, but since I have encountered
it not before today in one of my commercial projects (XHR had not been a
priority there), and a Google Groups search here for "1223" returned it only
once in a rather long posting of Conrad Lender that advocates browser
sniffing to deal with this kind of problem[1], I thought I could as well
tell you about it.

It was reported to Prototype a little more than a year ago [...]

I know. Read again:
In a nutshell:

As described e.g. in [2], contrary to the MSDN Library documentation[3], the ^^^^^^^^^^^^^^^^^^^^^^^^
IXMLHTTPRequest implementation in MSXML HTTP (at least in IE 8.0 on Windows
XP SP3+) does not handle HTTP responses with status code 204 (No Content)
properly; the `status' property has the value 1223 then (which I found out
thanks to IE 8.0's built-in debugger). The used ActiveX/COM ProgID to
reproduce the bug was "Microsoft.XMLHTTP" which should select MSXML 3.0 or
earlier (AFAIK).[4]

As a result, I have changed

status: {
OK_EXPR: /\b(0|2\d\d)\b/,

// ...
}

into

status: {
/*
* NOTE: MSXML translates 204 to 1223, see
* https://prototype.lighthouseapp.com/projects/[...]
*/
OK_EXPR: /\b(0|2\d\d|1223)\b/,

Don't you think regex is really a wrong tool for the job in this case?

No. Here I have the positive (and negative) cases composed into one
"constant"; for considering MSXML's quirk now, I did not need to modify the
code of a single method. Think about it.
It would be much more clear and efficient to perform a plain number
comparison.

As for clarity, I don't think so. As for efficiency, maybe; but iff number
comparison is more efficient, is the difference really relevant?
E.g., quoting YUI,
<http://github.com/yui/yui3/blob/7f5d4982cb5e88b379f9b3b8bea8e3acf810a511/src/io/js/io-base.js#L671>

if (status >= 200 && status < 300 || status === 1223) {

Yes, I know that and I don't like it at all.


PointedEars
 
T

Thomas 'PointedEars' Lahn

kangax said:
Thomas said:
kangax said:
Thomas 'PointedEars' Lahn wrote:
[...]
status: {
/*
* NOTE: MSXML translates 204 to 1223, see
* https://prototype.lighthouseapp.com/projects/[...]
*/
OK_EXPR: /\b(0|2\d\d|1223)\b/,
Don't you think regex is really a wrong tool for the job in this case?
No. Here I have the positive (and negative) cases composed into one
"constant"; for considering MSXML's quirk now, I did not need to modify the
code of a single method. Think about it.

Which negative case are you talking about?

It could be argued that what doesn't match the positive case can be
considered the negative one; thus the expression for the positive case could
be reused. However, I define and use

FAILED_EXPR: /\b[45]\d\d\b/,

among others, instead, which is what I was referring to.
Yes, you did not need to modify "code of a single method"; you modified
regex value of a property.

Not just any property.
Is there some substantial difference I'm not seeing here?

Modifying the property requires much less effort than modifying the method.
And as in my library the response listener can be user-defined (a setter can
shadow the inherited method), the RegExp provides the user which much an
easier-to-use tool to refine their listener without the need to depend on
the RegExp.
Efficiency difference most definitely doesn't matter. I am mainly
concerned about clarity in this case. It's not a big deal for simple
expression like that, but it will get cryptic as more "exceptions" are
added to it.

IBTD. Compare

if (oStatus.OK_EXPR.test(reqStatus))

against your

if (status >= 200 && status < 300 || status === 1223) {

and think about the mess (not) created (and efficiency [not] decreased) if
you need to handle another "exception". (Also think about the possible need
of renaming the `status' property some day; refactoring tools and
RegExp-search-and-replace don't always serve.)

Please trim your quotes.


PointedEars
 
D

Diego Perini

Thomas said:
kangax wrote: [...]
Is there some substantial difference I'm not seeing here?
Modifying the property requires much less effort than modifying the method.

Much less effort? I wouldn't say so, but I guess this is all rather
subjective.

Compare changing:

`OK_EXPR: /\b(0|2\d\d)\b/`
to:
`OK_EXPR: /\b(0|2\d\d|1223)\b/`

vs.

function isOK(code) { return code >= 200 && code < 300;}
to:
function isOK(code) { return code >= 200 && code < 300 || code == 1223;}

Is former example "much less" effort, really?
And as in my library the response listener can be user-defined (a setter can
shadow the inherited method), the RegExp provides the user which much an
easier-to-use tool to refine their listener without the need to depend on
the RegExp.

Perhaps it does make sense in your case. However, don't forget that
method allows to hide implementation details, whereas property doesn't.
If you make that property part of public interface, it will definitely
be messier to change it in the future (comparing to method whose
implementation is encapsulated within, and can be changed without
affecting anything depending on it). Think about it ;)




IBTD.  Compare
  if (oStatus.OK_EXPR.test(reqStatus))
against your
  if (status >= 200 && status < 300 || status === 1223) {

Apples, oranges.

No need to compare 2 different abstraction levels.

Here's a more even comparison, first on a higher level -

   if (oStatus.OK_EXPR.test(reqStatus))
   vs.
   if (isStatusOK(reqStatus))

- then, on a lower one -

   OK_EXPR: /\b(0|2\d\d|1223)\b/
   vs.
   function isStatusOK(code){
     return code >= 200 && code < 300 || code == 1223;
   }

Obviously, the clarity of latter example is the one I was talking about.

[...]

Remember that "1223" is not the only exception status code here.

Mozilla/Firefox can return a status code of "0" for some type of
network errors while it will return "408" for network timeout.

IE may return these extra status codes in case of network errors/
timeouts:

- 12002 ERROR_INTERNET_TIMEOUT
- 12007 ERROR_INTERNET_NAME_NOT_RESOLVED
- 12029 ERROR_INTERNET_CANNOT_CONNECT
- 12030 ERROR_INTERNET_CONNECTION_ABORTED
- 12031 ERROR_INTERNET_CONNECTION_RESET
- 12150 ERROR_HTTP_HEADER_NOT_FOUND
- 12152 ERROR_HTTP_INVALID_SERVER_RESPONSE

Also, status code "304 Not modified" is not exactly an error so both
code examples I see here are not handling these situation correctly.
OK_EXPR: /\b(0|2\d\d|1223)\b/
vs.
function isStatusOK(code){
return code >= 200 && code < 300 || code == 1223;
}

I agree that there is no need to detect/notify all errors
specifically, though some of them should be treated differently.

This obviously only applies if you deem "works well enough" not
sufficient as the target for your code.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top