Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions proxy.php
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,9 @@ function withProxyTracking(
$tokenAuth,
$includeProxyToken
) {
// Unset first so these are always appended last, not left at an existing key's position.
unset($params['cip'], $params['token_auth']);

// The entry is clean (no cip of its own), so set the real visitor IP.
$params['cip'] = $visitIp;

Expand Down
51 changes: 51 additions & 0 deletions tests/ProxyTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,57 @@ public function test_bulk_request_with_offending_entry_does_not_set_top_level_to
$this->assertStringNotContainsString('"token_auth":"<token>"', $responseBody);
}

public function test_bulk_request_injected_entry_token_is_appended_last_even_when_entry_supplies_token_auth_key()
{
// Clean entry already carries a token_auth key; the offending entry triggers per-entry injection.
$body = '{"requests":["?idsite=1&rec=1&action_name=off1&country=ru","?idsite=1&rec=1&token_auth=&action_name=clean&new_visit=1"]}';

$response = $this->send(
'raw_input=1',
null,
null,
['content-type' => 'application/x-www-form-urlencoded'],
null,
'POST',
$body
);

$responseBody = $this->getBody($response);

$this->assertEquals(200, $response->getStatusCode());

// The injected token is appended at the end of the entry (immediately before the JSON string
// terminator), not at the position the entry's own token_auth key happened to occupy.
$this->assertStringContainsString('token_auth=<token>"', $responseBody);
$this->assertStringNotContainsString('token_auth=<token>&', $responseBody);
}

public function test_bulk_request_drops_entry_token_auth_key_when_no_per_entry_token_is_injected()
{
// Fully clean batch: the proxy authorizes it with a single top-level token, so entries get no
// per-entry token. A token_auth key already present in an entry is dropped, not left in place.
$body = '{"requests":["?idsite=1&rec=1&token_auth=&action_name=clean&new_visit=1"]}';

$response = $this->send(
'raw_input=1',
null,
null,
['content-type' => 'application/x-www-form-urlencoded'],
null,
'POST',
$body
);

$responseBody = $this->getBody($response);

$this->assertEquals(200, $response->getStatusCode());
// The batch is authorized once at the top level (JSON form) and the entry gets cip only.
$this->assertStringContainsString('"token_auth":"<token>"', $responseBody);
$this->assertStringContainsString('action_name=clean&new_visit=1&cip=', $responseBody);
// The entry's own token_auth key is dropped: no key=value token_auth survives in any entry.
$this->assertStringNotContainsString('token_auth=', $responseBody);
}

public function test_bulk_request_leaves_offending_object_entry_untouched()
{
$body = '{"requests":[{"idsite":"1","rec":"1","action_name":"clean"},{"idsite":"1","cip":"6.6.6.6"}]}';
Expand Down
Loading