HTTP error 191

Thursday 6 October 2005

At work we had a thorny problem in our code: when trying to make an HTTP connection for a SOAP call, the connection would fail. Reading the log files, it seemed to be a 191 error. "That's odd, never heard of that one before," we all said. Somehow, the spec with all the HTTP errors had never heard of it either. Could it be some vendor-specific code? We were stumped.

We lived with it for a while until a co-worker figured it out. Our logging code looked like this:

if (FAILED(hresult)) {
    os << "hresult: " << std::hex << hresult << "\n";
}
if (lasterror > 0) {
    os << "Win32 error: " << lasterror << "\n";
}
if (httperror > 0) {
    os << "HTTP status: " << httperror << "\n";
}

Can you see what's going on here? Bueller? Anybody?

The std::hex function modifies the ostream permanently. If the hresult was printed, then the ostream was switched into hex mode, and all numbers will be hex. The httperror value (and the lasterror value for that matter) are being written in hexadecimal. The mysterious 191 error was actually a 0x191 error, or a plain-old 401. Inserting a std::dec to set the ostream back to decimal fixed things up. We still had to fix the "unauthorized" error, but at least now we know what it is!

Comments

[gravatar]
Bob 2:36 AM on 7 Oct 2005

Thanks for the reminder of how much I hated the C++ iostream package. In addition to the std::hex/std::dec problem there's also the ugly syntax. Overloading bitshift operators? WTF? Ugly syntax like this:
   os << "hresult: " << std::hex << hresult << std::dec << "\n";

Is so much easier to read in classic stdio:
   fprintf( os, "hresult: %x\n", hresult );

Iostreams may be typesafe and potentially less error prone (obviously not always!) but printf is much more succinct. Even Java has added printf support.

[gravatar]
Jonathon Duerig 12:06 PM on 7 Oct 2005

This is a situation where state-savers are really useful. You solved your proximate problem, but a new bug could crop up any time if you change another attribute somewhere else. However, if you use state-savers from boost in a disciplined manner, then this would be solved for all time:

http://www.boost.org/libs/io/doc/ios_state.html

The idea is that they are stack objects which save stream state in their constructor and restore that state in their destructor. Therefore, you just create one of them in the scope of any function that changes a stream attribute and that attribute will be restored when that function exits.

[gravatar]
Bob 5:42 PM on 7 Oct 2005

Jonathan,

Interesting link. A clever way to workaround this issue. But I still believe that formatting is something that should be associated with strings or a separate text formatter, not directly in IO streams. The Boost format library looks like it fits the bill nicely. Too bad they overloaded the mod operator to use it but the syntax isn't that bad. For example:

cout << format("Hello %s, x=%s : %d-th step \n") % "world" % 40.23 % 50;

Add a comment:

name
email
Ignore this:
not displayed and no spam.
Leave this empty:
www
not searched.
 
Name and either email or www are required.
Don't put anything here:
Leave this empty:
URLs auto-link and some tags are allowed: <a><b><i><p><br><pre>.