Couldn't get Header value -- Error occured "ICAP protocol error"

Asked by Ali Mohammad on 2009-04-09

Hi All,

I am new to ECAP lib and working on sample content adapter "ecap_adapter_sample-0.0.2". My packages and system specs are:

1. OS: Centos5.0
2. Squid: 3.1.0.6
3. libecap: 0.0.2

I am trying to get the header field for a browser request, say "Host: www.google.com", where name is "Host" and value is "www.google.com". My code is as:

void Adapter::Xaction::start() {
 Must(hostx);
 if (hostx->virgin().body()) {
  receivingVb = opOn;
  hostx->vbMake(); // ask host to supply virgin body
 } else {
  receivingVb = opNever;
 }

 libecap::shared_ptr<libecap::Message> adapted = hostx->virgin().clone();
     Must(adapted != 0);

 adapted->header().removeAny(libecap::headerContentLength);

 // add a custom header
 static const libecap::Name name("X-Ecap");
 const libecap::Header::Value value =
  libecap::Area::FromTempString(libecap::MyHost().uri());
 adapted->header().add(name, value);

 cout << "1. I am at "<< __LINE__ << endl;

 const libecap::Name name2("Host");
 libecap::Header::Value value1 ;

 cout << "2. I am at "<< __LINE__ << endl;
 value1 = adapted->header().value( name2 );

 if (!adapted->body()) {
  sendingAb = opNever; // there is nothing to send
  lastHostCall()->useAdapted(adapted);
 } else {
  hostx->useAdapted(adapted);
 }
}

When the execution reaches at line "cout << "2. I am at "<< __LINE__ << endl;", It displays the following error on browser:

------------------
    ICAP protocol error.
The system returned: [No Error]
This means that some aspect of the ICAP communication failed.
Some possible problems are:
    * The ICAP server is not reachable.
    * An Illegal response was received from the ICAP server.
------------------
please suggest me what I am doing wrong? I think there is a bug in value() function.

Any help would be greatly appreciated.

Thanks in advance.
Ali Muhammad

Question information

Language:
English Edit question
Status:
Solved
For:
eCAP Edit question
Assignee:
No assignee Edit question
Solved by:
Ali Mohammad
Solved:
2009-04-20
Last query:
2009-04-20
Last reply:
2009-04-15
Alex Rousskov (rousskov) said : #1

The error probably happens after you call useAdapted(). I would recommend collecting full Squid logs (debug_options ALL,9 in squid.conf) and analyzing the reason for the error that way.

Your analysis may be easier if you use libecap debugging methods because then you will see your debugging lines in Squid cache.log, along with Squid debugging lines.

Feel free to attach your cache.log here if you need help with the analysis.

Ali Mohammad (ali-mohammad) said : #2

Alex, Thanks for quick reply.

You can find my cache.log at:
http://dc141.4shared.com/download/97748992/963ef8ad/cache.log?tsid=20090410-073323-f5f3e0c9

I noticed that exception occurred at ICAP/AsyncJob.cc line 218, please see the cache.log line 6340, while processing the header, I traced out this exception but could not get the clue. when I comment out the above added code (value() function ) then this exception goes away.

Please have a look at log and suggest me what should I do to remove this error.

Thanks
Ali Muhammad

Alex Rousskov (rousskov) said : #3

Please see a Squid bug report and a patch at http://www.squid-cache.org/bugs/show_bug.cgi?id=2633

Alex Rousskov (rousskov) said : #4

Once you test the linked patch, please let me know whether it helps.

Thank you.

Ali Mohammad (ali-mohammad) said : #5

I applied patch, recompiled and installed squid, but no luck -- the same error. Even when I call
"hasAny(" function the same error occurred.

Error is:

"2009/04/13 11:29:46.938| ICAP/AsyncJob.cc(218) dial: AsyncJob::noteStart threw exception: basic_string::_S_construct NULL not valid".

Waiting for your feedback.
Thanks

Alex Rousskov (rousskov) said : #6

Perhaps there are other places were std::strings are constructed from nil pointers. It would help to know exactly what code path results in the std::string exception being thrown.

Can you run Squid from gdb or another debugger and set a breakpoint in your debugger to stop on the std::logic_error constructor(s)? When the debugger stops Squid, verify that it has happened when Adapter::Xaction::start() is in progress and collect the backtrace.

Alternatively, you can try to step through Adapter::Xaction::start() execution but that may be painful.

Another option is to set a breakpoint inside the basic_string constructor, exactly where the exception is being thrown.

For all of the above, you probably want to rebuild Squid with --disable-optimizations.

Once again, the goal is to produce a backtrace exposing the code that results in std::basic_string being constructed from a nil pointer.

Thank you.

Ali Mohammad (ali-mohammad) said : #7

Thanks for suggestion, I debugged the squid code by inserting debugging statements in several functions and finally (In my opinion) found that function "String HttpHeader::getList(http_hdr_type id) const" in file "squid-3.1.0.6/src/HttpHeader.cc" returns empty string (NULL pointer).

 if (!CBIT_TEST(mask, id)) {
    return String();
}
The execution reaches in this condition and constructor ( String() ) returns empty string.

I am searching the "Content-Encoding" field in http header say for "ask.com", The header contains this field but I am gettng null pointer.

Please have a look at the following attachment ( http header captured by 'firefox live http header' plugin):
http://dc144.4shared.com/download/98461891/79e1dd8d/header.txt?tsid=20090414-050611-8a30350f

As you can see not all headers in this file contains "Content-Encoding" field, In such case can I get/find value (using hasAny() and value() function)? for attached header I am getting NULL pointer for "Content-Encoding" tag.

Thanks for your help.

Alex Rousskov (rousskov) said : #8

HttpHeader and other Squid objects may return empty Strings. That is not the problem. However, Squid eCAP code must not try to convert an empty String into a std::string object. That's when std::basic_string construction code throws an exception.

I need a backtrace or equivalent to help you. Which adaptation/ecap/* method converts an empty String into a std::string object?

You can probably find this out by inserting debugging statements, but it may be faster and easier to do that by inserting a breakpoint in a debugger like gdb. See my previous response for details.

Thank you.

Ali Mohammad (ali-mohammad) said : #9

I debugged the code using gdb -- but could'nt trace out where the actual problem lies.

Please let me know if you have the solution.

Thanks for all your help.
Ali

Alex Rousskov (rousskov) said : #10

I need more info to start working on a solution.

Have you rebuild Squid with optimizations disabled?

When you run Squid under gdb, have you setup the breakpoint for std::logic_error constructor(s) or for the line in basic_string where the exception is being thrown? Was your breakpoint reached? If yes, please paste the output of the gdb "where" command when the breakpoint is reached.

Thank you,

Alex.

Ali Mohammad (ali-mohammad) said : #11

Thanks for being responsive. My apologize for responding so late (I was on leave).

-- Have you rebuild Squid with optimizations disabled?
Amazing, after rebuilding Squid with optimizations disabled, I did'nt get the above mentioned error.

Also, the following call works for me:
"hostx->cause().header().value("
instead of "adapted->header().value(" . Now am I am not getting any error.

Thanks,
Ali