Skip to content

Commit

Permalink
Update WebClient and its tests; update build
Browse files Browse the repository at this point in the history
  • Loading branch information
oleksandr-gribiennikov-paysera committed Apr 30, 2024
1 parent 506ebbf commit 08fd26a
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 45 deletions.
35 changes: 18 additions & 17 deletions WebToPay.php
Original file line number Diff line number Diff line change
Expand Up @@ -1150,37 +1150,38 @@ class WebToPay_WebClient
* @param array<string, mixed> $queryData
*
* @return string
*
* @throws WebToPayException
*/
public function get(string $uri, array $queryData = []): string
{
// Append query data to the URI if provided
if (!empty($queryData)) {
$uri .= (strpos($uri, '?') === false ? '?' : '&')
. http_build_query($queryData, '', '&');
if (count($queryData) > 0) {
$uri .= strpos($uri, '?') === false ? '?' : '&';
$uri .= http_build_query($queryData, '', '&');
}

// Parse URL
$url = parse_url($uri);
$scheme = $url['scheme'] ?? 'http';
$host = $url['host'] ?? '';
$port = $scheme === 'https' ? 443 : 80;
$path = $url['path'] ?? '/';
$query = isset($url['query']) ? '?' . $url['query'] : '';
if ('https' === ($url['scheme'] ?? '')) {
$host = 'ssl://' . ($url['host'] ?? '');
$port = 443;
} else {
$host = $url['host'] ?? '';
$port = 80;
}

// Open socket connection
$fp = $this->openSocket($host, $port, $errno, $errstr, 30);
if (!$fp) {
throw new WebToPayException(sprintf('Cannot connect to %s', $uri), WebToPayException::E_INVALID);
}

// Construct HTTP request
$out = "GET {$path}{$query} HTTP/1.1\r\n";
$out .= "Host: {$host}\r\n";
if(isset($url['query'])) {
$data = ($url['path'] ?? '') . '?' . $url['query'];
} else {
$data = ($url['path'] ?? '');
}

$out = "GET " . $data . " HTTP/1.0\r\n";
$out .= "Host: " . ($url['host'] ?? '') . "\r\n";
$out .= "Connection: Close\r\n\r\n";

// Send request and read response
$content = $this->getContentFromSocket($fp, $out);

// Separate header and content
Expand Down
10 changes: 4 additions & 6 deletions run_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,13 @@ container='lib_webtopay_tests'

if [ "$(docker ps -a -q -f name=$container)" ]; then
docker stop $container
docker rm $container
docker container rm --force $container
docker image rm $container
fi
docker build -t $container -f $PWD/Dockerfile --build-arg PHP_VER=7.4 $PWD

docker run -d --name $container -v $PWD:/var/www -w /var/www $container
#docker exec $container bash -c "composer i"

docker exec -it $container bash
docker exec $container bash -c "composer i"
#docker exec -it $container bash
docker exec $container bash -c "composer run phpunit"
docker container stop $container
#docker container rm --force $container
#docker image rm $container
35 changes: 18 additions & 17 deletions src/WebToPay/WebClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,37 +15,38 @@ class WebToPay_WebClient
* @param array<string, mixed> $queryData
*
* @return string
*
* @throws WebToPayException
*/
public function get(string $uri, array $queryData = []): string
{
// Append query data to the URI if provided
if (!empty($queryData)) {
$uri .= (strpos($uri, '?') === false ? '?' : '&')
. http_build_query($queryData, '', '&');
if (count($queryData) > 0) {
$uri .= strpos($uri, '?') === false ? '?' : '&';
$uri .= http_build_query($queryData, '', '&');
}

// Parse URL
$url = parse_url($uri);
$scheme = $url['scheme'] ?? 'http';
$host = $url['host'] ?? '';
$port = $scheme === 'https' ? 443 : 80;
$path = $url['path'] ?? '/';
$query = isset($url['query']) ? '?' . $url['query'] : '';
if ('https' === ($url['scheme'] ?? '')) {
$host = 'ssl://' . ($url['host'] ?? '');
$port = 443;
} else {
$host = $url['host'] ?? '';
$port = 80;
}

// Open socket connection
$fp = $this->openSocket($host, $port, $errno, $errstr, 30);
if (!$fp) {
throw new WebToPayException(sprintf('Cannot connect to %s', $uri), WebToPayException::E_INVALID);
}

// Construct HTTP request
$out = "GET {$path}{$query} HTTP/1.1\r\n";
$out .= "Host: {$host}\r\n";
if(isset($url['query'])) {
$data = ($url['path'] ?? '') . '?' . $url['query'];
} else {
$data = ($url['path'] ?? '');
}

$out = "GET " . $data . " HTTP/1.0\r\n";
$out .= "Host: " . ($url['host'] ?? '') . "\r\n";
$out .= "Connection: Close\r\n\r\n";

// Send request and read response
$content = $this->getContentFromSocket($fp, $out);

// Separate header and content
Expand Down
34 changes: 29 additions & 5 deletions tests/WebToPay/WebClientTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,32 +20,56 @@ public function testGet_NoSocket()
{
$this->webClientMock->expects($this->once())
->method('openSocket')
->with('example.com', 443)
->with('ssl://example.com', 443)
->willReturn(false);

$this->expectException(WebToPayException::class);
$this->expectExceptionMessage('Cannot connect to https://example.com?param1=value1&param2=value2');
$this->webClientMock->get('https://example.com', ['param1' => 'value1', 'param2' => 'value2']);
}

public function testGet()
public function getDataForTestingGet(): iterable
{
yield 'not secure' => [
'uri' => '',
'host' => '',
'host prefix' => '',
'port' => 80,
'scheme' => 'http',
];

yield 'secure' => [
'uri' => 'https://example.com',
'host' => 'example.com',
'host prefix' => 'ssl://',
'port' => 443,
'scheme' => 'https',
];
}

/**
* @dataProvider getDataForTestingGet
*
* @throws WebToPayException
*/
public function testGet(string $uri, string $host, string $hostPrefix, int $port, string $scheme)
{
$this->webClientMock->expects($this->once())
->method('openSocket')
->with('example.com', 443)
->with($hostPrefix . $host, $port)
->willReturn('socket');

$this->webClientMock->expects($this->once())
->method('getContentFromSocket')
->with(
'socket',
"GET /?param1=value1&param2=value2 HTTP/1.1\r\nHost: example.com\r\nConnection: Close\r\n\r\n"
"GET ?param1=value1&param2=value2 HTTP/1.0\r\nHost: {$host}\r\nConnection: Close\r\n\r\n"
)
->willReturn("HTTP/1.1 200 OK\r\n\r\nContent");

$this->assertEquals(
'Content',
$this->webClientMock->get('https://example.com', ['param1' => 'value1', 'param2' => 'value2'])
$this->webClientMock->get($uri, ['param1' => 'value1', 'param2' => 'value2'])
);
}
}

0 comments on commit 08fd26a

Please sign in to comment.