You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

99 lines
3.9 KiB

<?php
namespace p3k\HTTP\Tests;
use p3k\HTTP;
use PHPUnit\Framework\TestCase;
class SafeModeTest extends TestCase {
const DNS = [
'a.example' => ['93.184.216.34'],
'b.example' => ['93.184.216.35', '2606:2800:220:1::'],
'internal.example' => ['10.0.0.5'],
];
private function http(array $responses, &$transport) {
$transport = new RecordingTransport($responses);
$http = new HTTP('test', $transport);
$http->set_safe_mode(true, [], function($host) { return self::DNS[$host] ?? []; });
return $http;
}
public function testBlockedUrlMakesNoRequest() {
$http = $this->http([], $transport);
foreach(['gopher://127.0.0.1:6379/_FLUSHALL', 'file:///etc/passwd', 'http://127.0.0.1/', 'https://internal.example/'] as $url) {
$response = $http->post($url, 'x');
$this->assertSame('blocked_url', $response['error'], $url);
$this->assertSame(0, $response['code']);
}
$this->assertSame([], $transport->requests);
}
public function testRequestIsPinnedToCheckedAddresses() {
$http = $this->http(['https://b.example/' => [200, '', 'ok']], $transport);
$response = $http->get('https://b.example/');
$this->assertSame(200, $response['code']);
$this->assertSame(['b.example:443:93.184.216.35,[2606:2800:220:1::]'], $transport->requests[0]['pinned']);
$this->assertSame(0, $transport->max_redirects);
}
public function testRedirectToPrivateAddressIsRefused() {
$http = $this->http([
'https://a.example/' => [302, "Location: http://169.254.169.254/latest/meta-data/\r\n", ''],
], $transport);
$response = $http->get('https://a.example/');
$this->assertSame('blocked_url', $response['error']);
$this->assertCount(1, $transport->requests);
}
public function testRedirectToOtherSchemeIsRefused() {
$http = $this->http([
'https://a.example/token' => [307, "Location: gopher://a.example:6379/_x\r\n", ''],
], $transport);
$this->assertSame('blocked_url', $http->post('https://a.example/token', 'code=1')['error']);
$this->assertCount(1, $transport->requests);
}
public function testRedirectsAreFollowedKeepingMethodAndBody() {
$http = $this->http([
'https://a.example/one' => [301, "Location: /two\r\n", ''],
'https://a.example/two' => [200, "Content-Type: text/plain\r\n", 'done'],
], $transport);
$response = $http->post('https://a.example/one', 'body', ['Authorization: Bearer secret']);
$this->assertSame(200, $response['code']);
$this->assertSame('done', $response['body']);
$this->assertSame('https://a.example/two', $response['url']);
$this->assertSame('POST', $transport->requests[1]['method']);
$this->assertSame('body', $transport->requests[1]['body']);
$this->assertContains('Authorization: Bearer secret', $transport->requests[1]['headers']);
}
public function testCredentialsAreDroppedWhenARedirectLeavesTheOrigin() {
$http = $this->http([
'https://a.example/' => [302, "Location: https://b.example/\r\n", ''],
'https://b.example/' => [200, '', 'ok'],
], $transport);
$http->get('https://a.example/', ['Authorization: Bearer secret', 'Cookie: a=b', 'Accept: text/html']);
$this->assertSame(['Accept: text/html', 'User-Agent: test'], $transport->requests[1]['headers']);
}
public function testTooManyRedirects() {
$http = $this->http([
'https://a.example/loop' => [302, "Location: /loop\r\n", ''],
], $transport);
$http->set_max_redirects(3);
$response = $http->get('https://a.example/loop');
$this->assertSame('too_many_redirects', $response['error']);
$this->assertCount(4, $transport->requests);
}
public function testOffByDefault() {
$transport = new RecordingTransport([]);
$http = new HTTP('test', $transport);
$this->assertFalse($http->safe_mode());
$http->get('http://127.0.0.1/');
$this->assertCount(1, $transport->requests);
$this->assertNull($transport->requests[0]['pinned']);
$this->assertSame(8, $transport->max_redirects);
}
}