Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WPScan API: Update x-ratelimit-remaining header functionality #304

Merged
merged 9 commits into from
Oct 17, 2022
27 changes: 24 additions & 3 deletions http-functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -244,15 +244,35 @@ function vipgoci_http_resp_sunset_header_check(
* @param array $resp_headers HTTP response headers.
*
* @return void
*
* @codeCoverageIgnore
*/
function vipgoci_http_api_rate_limits_check(
string $http_api_url,
array $resp_headers
) :void {
/*
* Special case for WPScan API: Unlimited requests
* are indicated with a negative number for
* x-ratelimit-remaining header. Here we ignore
* such headers for WPScan API responses.
*/
if (
( true === str_starts_with(
$http_api_url,
VIPGOCI_WPSCAN_API_BASE_URL,
) ) &&
( isset( $resp_headers['x-ratelimit-remaining'][0] ) ) &&
( is_numeric( $resp_headers['x-ratelimit-remaining'][0] ) ) &&
( $resp_headers['x-ratelimit-remaining'][0] < 0 )
) {
return;
}

/*
* Look for ratelimit header.
*/
if (
( isset( $resp_headers['x-ratelimit-remaining'][0] ) ) &&
( is_numeric( $resp_headers['x-ratelimit-remaining'][0] ) ) &&
( $resp_headers['x-ratelimit-remaining'][0] <= 1 )
) {
vipgoci_sysexit(
Expand All @@ -261,7 +281,8 @@ function vipgoci_http_api_rate_limits_check(
array(
'http_api_url' => $http_api_url,
'x-ratelimit-remaining' => $resp_headers['x-ratelimit-remaining'][0],
'x-ratelimit-limit' => $resp_headers['x-ratelimit-limit'][0],
'x-ratelimit-limit' => isset( $resp_headers['x-ratelimit-limit'][0] )
?? $resp_headers['x-ratelimit-limit'][0],
),
VIPGOCI_EXIT_GITHUB_PROBLEM,
true // Log to IRC.
Expand Down
116 changes: 116 additions & 0 deletions tests/unit/HttpFunctionsHttpApiRateLimitsCheckTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
<?php
/**
* Test vipgoci_http_api_rate_limits_check() function.
*
* @package Automattic/vip-go-ci
*/

declare(strict_types=1);

namespace Vipgoci\Tests\Unit;

use PHPUnit\Framework\TestCase;

/**
* Class that implements the testing.
*
* @runTestsInSeparateProcesses
* @preserveGlobalState disabled
*/
final class HttpFunctionsHttpApiRateLimitsCheckTest extends TestCase {
/**
* Data for the test.
*
* @var $TEST_DATA
*/
private const TEST_DATA = array(
array(
'url' => 'https://api.github.com/v1',
'headers' => array(),
'output' => '',
),
array(
'url' => 'https://api.github.com/v1',
'headers' => array( 'x-ratelimit-remaining' => array( '100' ) ),
'output' => '',
),
array(
'url' => 'https://api.github.com/v1',
'headers' => array( 'x-ratelimit-remaining' => array( '0' ) ),
'output' => '"Ran out of request limits for API, cannot continue without making further requests."' . PHP_EOL,
),
array(
'url' => 'https://api.github.com/v1',
'headers' => array( 'x-ratelimit-remaining' => array( '-1' ) ),
'output' => '"Ran out of request limits for API, cannot continue without making further requests."' . PHP_EOL,
),
array(
'url' => 'https://api.github.com/v1',
'headers' => array( 'x-ratelimit-remaining' => array( 'abc' ) ), // Invalid, not numeric.
'output' => '',
),
array(
'url' => 'https://wpscan.com/api/v3/plugins/test',
'headers' => array(),
'output' => '',
),
array(
'url' => 'https://wpscan.com/api/v3/plugins/test',
'headers' => array( 'x-ratelimit-remaining' => array( '100' ) ),
'output' => '',
),
array(
'url' => 'https://wpscan.com/api/v3/plugins/test',
'headers' => array( 'x-ratelimit-remaining' => array( '0' ) ),
'output' => '"Ran out of request limits for API, cannot continue without making further requests."' . PHP_EOL,
),
array(
'url' => 'https://wpscan.com/api/v3/plugins/test',
'headers' => array( 'x-ratelimit-remaining' => array( '-1' ) ),
'output' => '',
),
array(
'url' => 'https://wpscan.com/api/v3/plugins/test',
'headers' => array( 'x-ratelimit-remaining' => array( 'abc' ) ), // Invalid, not numeric.
'output' => '',
),
);

/**
* Setup function. Require files.
*
* @return void
*/
protected function setUp() :void {
require_once __DIR__ . '/../../defines.php';
require_once __DIR__ . '/../../http-functions.php';
require_once __DIR__ . '/helper/HttpFunctionsHttpApiRateLimitsCheck.php';
}

/**
* Test different ratelimits headers when calling the function.
*
* @covers ::vipgoci_http_api_rate_limits_check
*
* @return void
*/
public function testRateLimits(): void {
foreach ( self::TEST_DATA as $test_item ) {
ob_start();

vipgoci_http_api_rate_limits_check(
$test_item['url'],
$test_item['headers']
);

$printed_data = ob_get_contents();
ob_end_clean();

$this->assertSame(
$test_item['output'],
$printed_data,
'Failed verifying with data: ' . json_encode( $test_item )
);
}
}
}
32 changes: 32 additions & 0 deletions tests/unit/helper/HttpFunctionsHttpApiRateLimitsCheck.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php
/**
* Helper function implementation for
* HttpFunctionsHttpApiRateLimitsCheckTest test.
*
* @package Automattic/vip-go-ci
*/

declare(strict_types=1);

// phpcs:disable VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
/**
* Print string $str when called.
*
* @param string $str Message.
* @param array $debug_data Debug data (not used).
* @param int $exit_status Exit status (not used).
* @param bool $irc (not used).
*
* @return void
*/
function vipgoci_sysexit(
string $str,
array $debug_data = array(),
int $exit_status = VIPGOCI_EXIT_USAGE_ERROR,
bool $irc = false
) :void {
echo json_encode( $str ) . PHP_EOL;
}

// phpcs:enable VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable