possible to pass information from reqmod to respmod Xaction?

Asked by Tom on 2012-10-31

Is it possible to pass any information from the reqmod Xaction to the respmod Xaction that was generated due to the original request? I don't see a clear way to do this since each Xaction object is created independently and the request Xaction tends to be destroyed (or at least stopped) before the respond Xaction is even created. Perhaps the best I can do is modify the URI to include a parameter which the response will see, but is there some other way which wouldn't be visible to the user? Is there a way to add a header to the request which would be included in the response? Any other suggestion to link the request Xaction to its corresponding response Xaction?

Question information

Language:
English Edit question
Status:
Solved
For:
eCAP Edit question
Assignee:
No assignee Edit question
Solved by:
Alex Rousskov
Solved:
2012-11-01
Last query:
2012-11-01
Last reply:
2012-11-01
Alex Rousskov (rousskov) said : #1

If your host application supports meta-information exchange among adaptation services, then you can use that feature to set a meta header in the REQMOD transaction and then receive that meta header in the RESPMOD transaction. Your adapter code can use the meta header value to tie different eCAP transactions together. Meta headers are not visible to HTTP clients and servers.

For example, if you are using Squid, see the adaptation_masterx_shared_names option in squid.conf.documented.

Alex Rousskov (rousskov) said : #2

I converted a polished answer into an FAQ :
FAQ #2117: “How to pass information from REQMOD to RESPMOD?”.

Tom (web-l) said : #3

Thank you. That looks to be exactly the functionality that I need, and I am using Squid (3.2.3).

In addition to your FAQ, I also found this thread which references the clamav adapter:

https://answers.launchpad.net/ecap/+question/185627

From that I learned that the clamav adapter compares the name of the meta-information with libecap::metaVirusId. That is actually declared within the source of eCap itself, and not just within the library.

That seems to imply users must use only metadata that has already been defined by eCap. The example given in the squid documentation uses X-Subscriber-ID, which is also already declared, but the documentation implies that other names could be used. Is it always safe to use X-Subscriber-ID, or might X-Subscriber-ID be used by something else? I see the list of other names in libecap/common/names.cc. Should an adapter re-use a name already declared, or is it safer (or even allowable) to create a new "Name" within my adapter? For example, is this better/safer to include in my adapter?

const libecap::Name libecap::metaSubscriberId("X-MY-SPECIAL-ID", libecap::Name::NextId());

Tom (web-l) said : #4

As I look further at the clamav adapter example, I am confused. What is the difference between the Adapter::Xaction::option() function and the Adapter::Xaction::visitEachOption() function? It appears that both return/set the meta-information if asked.

For reference, below are the two methods from the clamav adapter. Both check if !virusId.empty() and then appear to return or set the information from virusId. What is the difference between these two functions?

const libecap::Area Adapter::Xaction::option(const libecap::Name &name) const
{
 if (name == libecap::metaVirusId && !virusId.empty())
  return libecap::Area(virusId.data(), virusId.size());

 return libecap::Area();
}

void Adapter::Xaction::visitEachOption(libecap::NamedValueVisitor &visitor) const
{
 if (!virusId.empty())
  visitor.visit(libecap::metaVirusId,
   libecap::Area(virusId.data(), virusId.size()));
}

Tom (web-l) said : #5

In the adapter_modifying.cc, Adapter::Service::setOne, I see the following test and comment:

if (name.assignedHostId())
  ; // skip host-standard options we do not know or care about

I thought this might be an indication that the meta-information might be passed to the service rather than directly to the Xaction, but I put in some debug statements and that does not appear to be the situation. setOne is only called upon initialization of each Service object.

The core of my confusion is that I cannot figure out how the RESPMOD receives the meta-information from REQMOD. It appears that the option() and visitEachOption() functions (shown in my previous message) both pass information which was already set in virusId (in the clamav adapter). It appears that either of those functions could be used in the REQMOD to set the meta-information, but I don't see how the RESPMOD receives it. The clamav implemention doesn't quite seem to follow the classic use case described in squid's adaptation_masterx_shared_names (http://www.squid-cache.org/Doc/config/adaptation_masterx_shared_names/). Would you please tell me how RESPMOD should receive the meta-information, perhaps offering a small line of code in the appropriate location?

Thanks in advance.

Tom (web-l) said : #6

OK, I figured out how RESPMOD can get the value. From this question:

https://answers.launchpad.net/ecap/+question/185627

I tried putting a call in my Xaction::start() function to do:

libecap::Header::Value subscriberId = hostx->option(libecap::metaSubscriberId) ;

That did contain the value which I set in both option() and visitEachOption().

So although I have found a solution, would you please answer 2 of the questions I asked above...

1.) Should we be using X-Subscriber-ID or creating our own with a command such as:

const libecap::Name libecap::metaSubscriberId("X-MY-SPECIAL-ID", libecap::Name::NextId());

2.) Would you please elaborate on the difference between Xaction::option() and Xaction::visitEachOption() since they both appear to be passing the same information in the clamav example?

Thanks in advance.

Best Alex Rousskov (rousskov) said : #7

Please open new questions to ask new questions.

In general, you may use any meta header name. Some names, such as X-Subscriber-ID (documented in an ICAP Internet Draft), are semi-standard, and so libecap or host applications may hard-code them for performance reasons. If their semantics matches your needs, it is a good idea to use them. Otherwise, you should introduce new names, specific to your application (to avoid clashes with other adapters).

The difference between options() and visitEachOption() is performance and convenience. One is of requesting a single known option (i.e., meta header). The other is for iterating all options. In most cases you want the former, but sometimes you have to do the latter (and pay the price in code complexity and speed).

Tom (web-l) said : #8

That's what I needed to know, and I have it working. Thanks.

Tom (web-l) said : #9

Thanks Alex Rousskov, that solved my question.

Alex, hello.

I need to share information, comming from REQMOD (by X-Session-ID header param) to RESPMOD.

Made all necessary configurations at squid.conf and create a plugin-project from samples of eCap.
So, I could see X-Session-ID: [value] at REQMOD in options() and visitEachOption() methods and I handle it as in ClamAv plugin (save it in variable of Xaction object), but I, realy, don't understand, how and where should I reseive it in RESPMOD?

Or, may be, I have to save it in shared memory by myself? but in this case, I didn't see any way to identify a request-responce transaction.

In any case, It seems to me, that it have to be a simple way to do such thing, but I couldn't see it.

Thanks in advance.
Alexey.

Alex Rousskov (rousskov) said : #11

> how and where should I reseive it in RESPMOD?

If your host application is configured to share metainformation among related eCAP transactions, then your RESPMOD transaction will receive that metainformation as a libecap::host::Xaction option. You can extract that info from the host transaction using the libecap::Options API of the libecap::host::Xaction object.

Thank You very much, Alex, for your help.

It works fine now.
So, I've found 2 ways to get params at RESPMOD:

1. libecap::Area val = hostx().cause().header().value(libecap::metaSubscriberId); // and
2. libecap::Area val = hostx().option(libecap::metaSubscriberId);

what way is more true or are they equal?

Alex Rousskov (rousskov) said : #13

> 1. libecap::Area val = hostx().cause().header().value(libecap::metaSubscriberId);

This gets a header field value from the HTTP request. While one can abuse HTTP headers for the purpose of sharing adaptation meta-information, it is usually a bad idea.

> 2. libecap::Area val = hostx().option(libecap::metaSubscriberId);

This is one of the right ways to get meta-information from the host transaction.

My earlier suggestions and the FAQ entry talk about #2, not #1.

Evgeny Petrov (groosha) said : #14

Could you please share a snipped how to set a custom meta info (f.ex. with name "X-ecap-id") and how to read it?