Request Satisfaction and body adapation

Asked by WorkingMan

I am reading your answer for #186565 but I couldn't find the source code for this adapter.

I want to do this:

1) capture a POST request (I added a special header when sending the request) in the adapter. Is this simply the body of the request (ie: get this in request mode)?

2) send a new response in the request mode (so doesn't need to go to response mode at all) and I need POST body to determine what to do.

I am not sure how this works but in my test it appears noteVbContentAvailable allows me to accumulate the content (is this content the actual response?). Based on the log that's what I am seeing. So how do I get the POST body?

Question information

Language:
English Edit question
Status:
Answered
For:
eCAP Edit question
Assignee:
No assignee Edit question
Last query:
Last reply:
Revision history for this message
WorkingMan (signup-mail2002) said :
#1

To clarify. It accumulates the body of the response and not the body of the request. I am assuming the body of the request will contain the body of a POST (ie: the request parameters in the body).

Revision history for this message
Alex Rousskov (rousskov) said :
#2

eCAP mostly treats requests and responses the same way. For example:

* If you configure the host application to use your eCAP service at pre-cache REQMOD vectoring point, your adapter will get a request message (with body, if any).

* If you configure the host application to use your eCAP service at pre-cache RESPMOD vectoring point, your adapter will get a response message (with body, if any).

Both messages can be accumulated and adapted the same way. The primary differences are:

* Request satisfaction mode described at Answer #186565 is only available at pre-cache REQMOD vectoring point.

* At pre-cache RESPMOD vectoring point, you can also get the corresponding request headers (but not the body) vide the cause() API.

* Message::firstLine() returns a RequestLine object for requests but a StatusLine object for responses.

If you want to analyze a request body, your adapter should work at the pre-cache REQMOD vectoring point. Same for request satisfaction.

Revision history for this message
WorkingMan (signup-mail2002) said :
#3

So are you saying for getting POST body (in the request body) I will need to do the same as if it was for a request?

Questions

1) So for response there is a call to hostx->vbMakeI(), are you saying this same call works for request as well? I just keep same logic as for response to obtain the request body?

2) I used the logic in #186565 plus addBody() (from #143545). It looks like I can supply empty body if I simply use 186565's logic in start(). When I added addBody it went to abMake() then stop(). There is no sample code so I have no clue what I am suppose to do to add content. Can you show us how it's done? I simply need to some string in the response.

Revision history for this message
Alex Rousskov (rousskov) said :
#4

1) Yes, various host::xaction::vb*() methods work for all messages. Same for most other message-related methods. HTTP requests and responses are very similar in structure so it does not make sense to have two separate sets of methods for them.

2) Several published adapters receive virgin body and supply adapted body. For example, adapter_modifying does both. IIRC, most (possibly all) adapter samples can work with both requests (REQMOD) and responses (RESPMOD); it is only a matter of host configuration.

Revision history for this message
WorkingMan (signup-mail2002) said :
#5

Can you explain a bit more.

1) When I try to capture the request body I am receiving the response body based on the dummy web page I have. In tshark from the server side I can see that I am receiving the proper header and POST body. All this happens in the request mode.

2) When I tried to create a new body (using code from 186565, but where is the full source code, I can't find it) it seems that I end too soon. After I call useAdapted it will cause a call to abMake but then immediately ends (ie: end the ab* flow so I end up with an empty body)

abMake:
 Must(sendingAb == opUndecided);
 Must(hostx->virgin().body());

 Must(receivingVb == opOn || receivingVb == opComplete);

 sendingAb = opOn;
 if(hostx) {
  hostx->noteAbContentAvailable();
        }

 sendingAb = opComplete;
 if(hostx) {
  hostx->noteAbContentDone(receivingVb == opComplete);

I think some subtle handling for request should be explained. I am really just guessing at how it should be done rather than knowing for sure how it should be done.

Thanks

Revision history for this message
Alex Rousskov (rousskov) said :
#6

1) If you are receiving a response body, then you are in RESPMOD. Fix your host application configuration.

2) Perhaps you should resolve #1 first, but in general, you should not call noteAbContentDone() until you have the last body byte buffered and available for the host transaction to take. The host transaction will take content when it is convenient for the host application to do so (via abContent() and abContentShift() methods).

Revision history for this message
WorkingMan (signup-mail2002) said :
#7

You are correct I am having issue receiving any event for request mode for some reason. My check for request mode was backwards so I confused myself with the wrong logging. Can you take a look at my question in SQUID forum (it has my squid.conf) to see if you can spot anything wrong with my configuration?

http://thread.gmane.org/gmane.comp.web.squid.general/104463/focus=104477

Thanks

Revision history for this message
Alex Rousskov (rousskov) said :
#8

Done. In summary, you were using a response-based condition for a pre-cache REQMOD vectoring point, which does not work because the response does not exist at that point.

Revision history for this message
WorkingMan (signup-mail2002) said :
#9

I made the change to "allow all" for REQMOD and I am receiving the POST body.

The final solution is like this (let me know if anything is wrong) as tested.

1) REQMOD should use "allow all"
2) First request has no content type so don't rely on that for your validation
3) call vbMake() in start()
4) Accumulate body in noteVbContentAvailable (same code as RESPMOD), if you need it
5) In noteVbContentDone you can initiate your new response or you could do it directly from start() I believe. I am not sure if you can get compressed body in request but it doesn't harm to let it go through your decompress logic. Use sample code from 186565. After useAdapted() it will trigger ab* methods
6) can reuse your RESPMOD code for abMake, abContent, abContentShift. Now my current response is small, i don't know what happens when it's bigger than one read by the host. I assume host app will read until it reaches end of buffer but how it determines that is beyond me (would be nice to explain this).

Revision history for this message
Alex Rousskov (rousskov) said :
#10

Glad you made it work and thank you for documenting your findings. I believe your descriptions is more or less accurate.

I am not sure what you mean by the "first request" -- there is no such concept in HTTP or eCAP. Each request has to be processed individually and does not really depend on other requests in most cases. This is especially true for eCAP because the host application may not send all requests to the adapter (due to configuration or other factors).

To determine whether a virgin message has a body, use the Message::body() method. It should return nil if the message lacks a body. As usual, this works for both requests and responses. Just keep in mind that you cannot access request body in RESPMOD. Please note that the entire virgin message body may not be available at start() time.

Yes, all messages may be compressed (e.g., Transfer-Encoding and/or Content-Encoding containing a "gzip" value), but compressed requests are rare.

To answer your last question: After the adapter calls the host::Xaction::noteAbContentDone() method, the host application may assume that the adapter transaction buffer contains the last body byte. Please note that the adapter can only append to its body buffer. It is the host transaction that consumes adapted content by calling adapter::Xaction::abContentShift() method when it is convenient for the host application to do so. For large adapted message bodies, one would expect many adapter::Xaction::abContent*() calls, as the host application will need to fill and write its own buffer many times.

Please try to use separate Questions for separate issues to make it easier to find the answers one is looking for.

Can you help with this problem?

Provide an answer of your own, or ask WorkingMan for more information if necessary.

To post a message you must log in.