matomo-org / tracker-proxy

HTTP proxy for Matomo's tracker API. This script allows to track websites with Matomo without revealing to your visitors the secret Matomo server URL.
http://matomo.org/faq/how-to/faq_132/
GNU General Public License v3.0
152 stars 46 forks source link

Bulk request did not send `cip` #86

Open ducdigital opened 10 months ago

ducdigital commented 10 months ago

It seems like tracker-proxy does not include token_auth and cip in bulk request . The X-Forwarded-For does not work with bulk requests on Matomo 5.

For all bulk requests, the server IP is used on Matomo instead of the real forwarded IP address.

I took some liberty to add a few more methods to the file, it works but I did not test it for PHP < 7.4.

What works:

What seems to be broken:

Here's the code:

function isUsingBulkRequest($rawData)
{
    if (!empty($rawData)) {
        return strpos($rawData, '"requests"') || strpos($rawData, "'requests'");
    }

    return false;
}

function processBulkQuery($query, $extraParam = []) {
    $cleanedQuery = $query;

    if (substr($query, 0, 1)) {
        $cleanedQuery = substr($query, 1);
    }

    $parsedQuery = array();
    $parsedUrl = parse_str($cleanedQuery, $parsedQuery);

    return '?' . http_build_query(array_merge($parsedQuery, $extraParam));
}

function buildAuthBulkRequest($rawData, $auth_token, $cip) {
    $jsonData = json_decode($rawData, $assoc = true);
    if (!isset($jsonData['requests'])) {
        return $rawData;
    }
    $jsonData['token_auth'] = $auth_token;

    $extraQueryParams = [
        "cip" => $cip,
    ];

    $jsonData['requests'] = array_map(
        function($query) use ($extraQueryParams) {
            return processBulkQuery($query, $extraQueryParams);
        },
        $jsonData['requests']
    );

    return json_encode($jsonData);
}

Add the following code in the POST handler will add cip to the individual query and token_auth on the post body:

        global $TOKEN_AUTH;
        $postBody = file_get_contents("php://input");
        $isBulk = isUsingBulkRequest($postBody);
...
        if($isBulk) {
            $stream_options['http']['content'] = buildAuthBulkRequest($postBody, $TOKEN_AUTH, $visitIp);
        }
        $stream_options['http']['header'][] = "Content-Length: " . strlen($postBody);

original requests :

{
    "requests": [
        "?action=Page",
    ],
    "send_image": 0
}

expected result:

{
    "requests": [
        "?action=Page&cip=0.0.0.0",
    ],
    "send_image": 0,
    "token_auth": "TOKEN_AUTH"
}