How to move a part of request URL into request header?

Asked by Ivan Kolesnikov

Hello Everyone,

I want transmit a COOKIE header value in URI and will correct requests via SQUID.
My request URI to SQUID will look as follow: www.example.com?cookie_val=12345
I need:
1. get the cookie_val from this URI
2. add the COOKIE header to request with value "cookie_val=12345"
3. remove this value from URI and make a get request to www.example.com with header "COOKIE" "cookie_val=12345"

1) I can solve the point 1 with help ClamAV adapter as in an answer https://answers.launchpad.net/ecap/+faq/1576
2) I can add a new header to request in ecapModifier adapter from the examples (ecap_adapter_sample-1.0.0)
     void Adapter::Xaction::start() {
             ...
             //add a Cookie Header
             static const libecap::Name name_cookie("Cookie");
             const libecap::Header::Value value_cookie = libecap::Area::FromTempString("cookie_val=12345");
             adapted->header().add(name_cookie, value_cookie);
            ...
     }
3) This answer is suitable for solve the point 3 https://answers.launchpad.net/ecap/+question/295401

Please advice and explain the best way to solve my issue. Can I solve all points (get uri, add request header and modify uri) by one adapter or I should use ecapModifier and ClamAV adapters together and how if yes? Or exist a better way to solve this issue?

Question information

Language:
English Edit question
Status:
Solved
For:
eCAP Edit question
Assignee:
No assignee Edit question
Solved by:
Alex Rousskov
Solved:
Last query:
Last reply:
Revision history for this message
Best Alex Rousskov (rousskov) said :
#1

> Can I solve all points (get uri, add request header and modify uri) by one adapter?

Yes, a single REQMOD adapter is sufficient to do what you want.

> should use ecapModifier and ClamAV adapters together?

You may use ideas/approaches 1-3 (from all the relevant open source adapters) to implement your adapter. You may use the sample modifying adapter as a starting point and then add/adjust code as needed to accomplish your goals. When you are done, you will have your own adapter that does what you want.

Revision history for this message
Ivan Kolesnikov (ikolesnikov) said :
#2

Alex,

Thank you for the answer!
I try to adjust the modifying adapter to reach my goals. All is fine with point 1-2. I can get an argument from URL and add it to the header in request. But I can't change the request URI. Please see the code:

void Adapter::Xaction::start() {
        ...

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

        //get the Cookie value from URL
        typedef const libecap::RequestLine *CLRLP;
        CLRLP requestLine = dynamic_cast<CLRLP>(&hostx->virgin().firstLine());
        std::string cookie_str = getCookieFromUri(requestLine->uri().toString());

        //add the Cookie header
        static const libecap::Name name_cookie("Cookie");
        const libecap::Header::Value value_cookie = libecap::Area::FromTempString(cookie_str);
        adapted->header().add(name_cookie, value_cookie);

        /*I THINK HERE I SHOULD ADJUST THE REQUEST LINE IN CLONED ADAPTED*/

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

As you can see I clone() the virgin message -> get Cookie from URL -> add this Cookie to Clone -> call useAdapted(), but I still not understand how to adjust the request line in cloned adapted. Can you please explain how to create this? I already checked https://answers.launchpad.net/ecap/+question/186565 and https://answers.launchpad.net/ecap/+question/295401 and ClamAV adapter v1.0.0 , but it's not helped for my understanding.

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

> https://answers.launchpad.net/ecap/+question/295401

I believe the answer to that question contains the information you are looking for (but not the corresponding code): You should call the RequestLine::uri(Area) method of the request line part of the adapted object. Did you try that?

Please note that for initial testing, you can just put any hard-coded URI (e.g., "http://example.com/"). Make sure that works before you spend time on the URI adjustments required for your project. If you get it working, please post a snippet here for others to reuse.

Revision history for this message
Ivan Kolesnikov (ikolesnikov) said :
#4

Hi Alex,
I tried to adjust the cloned adapted as follow:

void Adapter::Xaction::start() {
    ....
    libecap::shared_ptr<libecap::Message> adapted = hostx->virgin().clone();
    typedef const libecap::RequestLine *CLRLP;
    CLRLP myRequestLine = dynamic_cast<CLRLP>(&adapted->firstLine());
    const libecap::Area newUri = libecap::Area::FromTempString("http://www.example.com/");
    myRequestLine->uri(newUri);
    ....
    hostx->useAdapted(adapted);
}

But I received the following error message as RequestLine::uri(Area) is constant.
"error: passing ‘const libecap::RequestLine’ as ‘this’ argument discards qualifiers [-fpermissive] myRequestLine->uri(newUri);"

Please advice how I should do it correct.

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

Since you want to modify myRequestLine, you should not declare it to be constant:

    typedef libecap::RequestLine *LRLP;
    LRLP myRequestLine = dynamic_cast<LRLP>(&adapted->firstLine());

BTW, your "How to make this code compile" question is a general development question. Such questions are better asked on general forums such as StockOverflow.

Revision history for this message
Ivan Kolesnikov (ikolesnikov) said :
#6

Alex, thank you so much!
This is the working snippet as you requested:

void Adapter::Xaction::start() {
        ...
        //clone the virgin message
        libecap::shared_ptr<libecap::Message> adapted = hostx->virgin().clone();
        Must(adapted != 0);
        adapted->header().removeAny(libecap::headerContentLength);

        //get the Cookie value from URL
        typedef const libecap::RequestLine *CLRLP;
        CLRLP requestLine = dynamic_cast<CLRLP>(&hostx->virgin().firstLine());
        std::string cookie_str = getCookieFromUri(requestLine->uri().toString());

        //add the Cookie header
        static const libecap::Name name_cookie("Cookie");
        const libecap::Header::Value value_cookie = libecap::Area::FromTempString(cookie_str);
        adapted->header().add(name_cookie, value_cookie);

        //adjust the request line
        typedef libecap::RequestLine *LRLP;
        LRLP myRequestLine = dynamic_cast<LRLP>(&adapted->firstLine());
        const libecap::Area newUri = libecap::Area::FromTempString("http://www.example.com/");
        myRequestLine->uri(newUri);

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

Revision history for this message
Ivan Kolesnikov (ikolesnikov) said :
#7

Thanks Alex Rousskov, that solved my question.