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

Asked by Ivan Kolesnikov on 2017-04-04

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:
2017-04-26
Last query:
2017-04-26
Last reply:
2017-04-24
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.

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.

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.

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.

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.

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);
        }
}

Ivan Kolesnikov (ikolesnikov) said : #7

Thanks Alex Rousskov, that solved my question.