Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Apache module - get request body

Tags:

c++

linux

apache

I am creating simple apache module to capture all HTTP traffic for real time processing by security software. My goal is to get headers and body from both request and response. So far I managed to get all i need except request body. What's the best way to get request body in output filter, or in any other hook/handler to get request-response "tuple" with all releated information ?

static apr_status_t ef_output_filter(ap_filter_t *f, apr_bucket_brigade *bb)
{
    apr_status_t rv;

    request_rec *r = f->r;

    apr_bucket *e = APR_BRIGADE_FIRST(bb);
    const char *data;
    apr_size_t length;

    std::ofstream outfile;
    outfile.open("/var/log/apache2/test.txt", std::ios_base::app);

    outfile << r->method << r->unparsed_uri << std::endl;
    apr_table_do(loop_table, &outfile, r->headers_in, NULL);
    //!!! READ REQUST BODY HERE !!!!

    outfile << r->status << std::endl;
    apr_table_do(loop_table, &outfile, r->headers_out, NULL);
    outfile << std::endl;

    while (e != APR_BRIGADE_SENTINEL(bb)) {
        apr_bucket_read(e, &data, &length, APR_BLOCK_READ);
        e = APR_BUCKET_NEXT(e);
        outfile << data;
    }

    outfile.flush();
    outfile.close();

    return ap_pass_brigade(f->next, bb);
}

Any help appriciated

like image 516
Kryštof Hilar Avatar asked Sep 07 '26 16:09

Kryštof Hilar


1 Answers

You can read the body from the request_rec pointer you're deriving from the ap_filter_t pointer variable.

  1. As a first step, you should tell apache you want to read data from the client, by calling ap_setup_client_block, passing the request_rec pointer and a "read policy" as argument.
  2. Second, you call ap_should_client_block (passing the request_rec pointer as argument) to check everything is OK, especially on the client side (expecting true as result).
  3. Then you call (as many times as needed) ap_get_client_block, with the request_rec as argument, a buffer where the data will go, and the size of your buffer. You should get as a response the number of bytes read, and the data should be in your buffer. If you tried to read X bytes maximum and got X bytes returned, you should call again to get the remaining bytes. Note that the header "Content-length" should be use to avoid trying to read too many data, which might cause crashes...

So you'd go for something along the lines of:

char buffer[SOME_BUFER_SIZE];
int ret_code = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR);
if (ret_code == OK) {
    if (ap_should_client_block(r)) {
        int dataBytesRead = ap_get_client_block(r, buffer, SOME_BUFFER_SIZE);
        ...
    }
}

As of writing, you can find more info here: https://docstore.mik.ua/orelly/apache_mod/139.htm or here: http://byteandbits.blogspot.com/2013/09/example-apache-module-for-reading.html

Hope it helps...

like image 141
Francois Connetable Avatar answered Sep 10 '26 08:09

Francois Connetable