Skip to content

Commit a177d58

Browse files
committed
upgrade to integration tests 4
1 parent 94290f4 commit a177d58

File tree

9 files changed

+76
-58
lines changed

9 files changed

+76
-58
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ jobs:
2424
needs:
2525
- supported-versions-matrix
2626
strategy:
27+
fail-fast: false
2728
matrix:
2829
php: ${{ fromJson(needs.supported-versions-matrix.outputs.version) }}
2930

@@ -56,6 +57,7 @@ jobs:
5657
needs:
5758
- supported-versions-matrix
5859
strategy:
60+
fail-fast: false
5961
matrix:
6062
php: ${{ fromJson(needs.supported-versions-matrix.outputs.version) }}
6163

@@ -81,30 +83,3 @@ jobs:
8183

8284
- name: Execute tests
8385
run: composer test
84-
85-
coverage:
86-
name: Code Coverage
87-
runs-on: ubuntu-latest
88-
89-
steps:
90-
- name: Checkout code
91-
uses: actions/checkout@v4
92-
93-
- name: Setup PHP
94-
uses: shivammathur/setup-php@v2
95-
with:
96-
php-version: 8.3
97-
tools: composer
98-
coverage: xdebug
99-
100-
- name: Install dependencies
101-
run: composer update --prefer-dist --no-interaction --no-progress
102-
103-
- name: generate ssl
104-
run: cd ./tests/server/ssl && ./generate.sh && pwd && ls -la && cd ../../../
105-
106-
- name: boot test server
107-
run: vendor/bin/http_test_server > /dev/null 2>&1 &
108-
109-
- name: Execute tests
110-
run: composer test-ci

composer.json

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,17 @@
1717
"symfony/options-resolver": "^2.6 || ^3.4 || ^4.4 || ^5.0 || ^6.0 || ^7.0"
1818
},
1919
"require-dev": {
20+
"ext-openssl": "*",
2021
"friendsofphp/php-cs-fixer": "^3.51",
21-
"php-http/client-integration-tests": "^3.1.1",
22+
"php-http/client-integration-tests": "^4.0",
2223
"php-http/message": "^1.16",
2324
"php-http/client-common": "^2.7",
24-
"phpunit/phpunit": "^8.5.23 || ~9.5",
25+
"phpunit/phpunit": "^10.0 || ^11.0 || ^12.0",
2526
"php-http/message-factory": "^1.1"
2627
},
28+
"conflict": {
29+
"guzzlehttp/psr7": "<2.0"
30+
},
2731
"provide": {
2832
"php-http/client-implementation": "1.0",
2933
"psr/http-client-implementation": "1.0"

src/Client.php

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use Psr\Http\Message\RequestInterface;
1111
use Psr\Http\Message\ResponseFactoryInterface;
1212
use Psr\Http\Message\ResponseInterface;
13+
use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException;
1314
use Symfony\Component\OptionsResolver\Options;
1415
use Symfony\Component\OptionsResolver\OptionsResolver;
1516

@@ -28,16 +29,16 @@ class Client implements HttpClient
2829
use ResponseReader;
2930

3031
/**
31-
* @var array{remote_socket: string|null, timeout: int, stream_context: resource, stream_context_options: array<string, mixed>, stream_context_param: array<string, mixed>, ssl: ?boolean, write_buffer_size: int, ssl_method: int}
32+
* @var array{remote_socket: string|null, timeout: int, stream_context: resource, stream_context_options: array<string, mixed>, stream_context_param: array<string, mixed>, ssl: ?bool, write_buffer_size: int, ssl_method: int}
3233
*/
3334
private $config;
3435

3536
/**
3637
* Constructor.
3738
*
38-
* @param array{remote_socket?: string|null, timeout?: int, stream_context?: resource, stream_context_options?: array<string, mixed>, stream_context_param?: array<string, mixed>, ssl?: ?boolean, write_buffer_size?: int, ssl_method?: int}|ResponseFactoryInterface $config1
39-
* @param array{remote_socket?: string|null, timeout?: int, stream_context?: resource, stream_context_options?: array<string, mixed>, stream_context_param?: array<string, mixed>, ssl?: ?boolean, write_buffer_size?: int, ssl_method?: int}|null $config2 Mistake when refactoring the constructor from version 1 to version 2 - used as $config if set and $configOrResponseFactory is a response factory instance
40-
* @param array{remote_socket?: string|null, timeout?: int, stream_context?: resource, stream_context_options?: array<string, mixed>, stream_context_param?: array<string, mixed>, ssl?: ?boolean, write_buffer_size?: int, ssl_method?: int} $config intended for version 1 BC, used as $config if $config2 is not set and $configOrResponseFactory is a response factory instance
39+
* @param array{remote_socket?: string|null, timeout?: int, stream_context?: resource, stream_context_options?: array<string, mixed>, stream_context_param?: array<string, mixed>, ssl?: ?bool, write_buffer_size?: int, ssl_method?: int}|ResponseFactoryInterface $config1
40+
* @param array{remote_socket?: string|null, timeout?: int, stream_context?: resource, stream_context_options?: array<string, mixed>, stream_context_param?: array<string, mixed>, ssl?: ?bool, write_buffer_size?: int, ssl_method?: int}|null $config2 Mistake when refactoring the constructor from version 1 to version 2 - used as $config if set and $configOrResponseFactory is a response factory instance
41+
* @param array{remote_socket?: string|null, timeout?: int, stream_context?: resource, stream_context_options?: array<string, mixed>, stream_context_param?: array<string, mixed>, ssl?: ?bool, write_buffer_size?: int, ssl_method?: int} $config intended for version 1 BC, used as $config if $config2 is not set and $configOrResponseFactory is a response factory instance
4142
*
4243
* string|null remote_socket Remote entrypoint (can be a tcp or unix domain address)
4344
* int timeout Timeout before canceling request
@@ -110,6 +111,7 @@ protected function createSocket(RequestInterface $request, string $remote, bool
110111
$socket = @stream_socket_client($remote, $errNo, $errMsg, floor($this->config['timeout'] / 1000), STREAM_CLIENT_CONNECT, $this->config['stream_context']);
111112

112113
if (false === $socket) {
114+
$errMsg = $errMsg ?: '[no message set]';
113115
if (110 === $errNo) {
114116
throw new TimeoutException($errMsg, $request);
115117
}
@@ -120,7 +122,13 @@ protected function createSocket(RequestInterface $request, string $remote, bool
120122
stream_set_timeout($socket, (int) floor($this->config['timeout'] / 1000), $this->config['timeout'] % 1000);
121123

122124
if ($useSsl && false === @stream_socket_enable_crypto($socket, true, $this->config['ssl_method'])) {
123-
throw new SSLConnectionException(sprintf('Cannot enable tls: %s', error_get_last()['message'] ?? 'no error reported'), $request);
125+
$errorMessage = error_get_last()['message'] ?? 'no error reported';
126+
$opensslErrors = $this->collectOpenSslErrors();
127+
if ('' !== $opensslErrors) {
128+
$errorMessage .= '; '.$opensslErrors;
129+
}
130+
131+
throw new SSLConnectionException(sprintf('Cannot enable tls method %s: %s', $this->config['ssl_method'], $errorMessage), $request);
124132
}
125133

126134
return $socket;
@@ -138,12 +146,25 @@ protected function closeSocket($socket)
138146
fclose($socket);
139147
}
140148

149+
/**
150+
* Collect and format OpenSSL error queue entries, if available.
151+
*/
152+
private function collectOpenSslErrors(): string
153+
{
154+
$errors = [];
155+
while (false !== ($error = openssl_error_string())) {
156+
$errors[] = $error;
157+
}
158+
159+
return implode(' | ', $errors);
160+
}
161+
141162
/**
142163
* Return configuration for the socket client.
143164
*
144-
* @param array{remote_socket?: string|null, timeout?: int, stream_context?: resource, stream_context_options?: array<string, mixed>, stream_context_param?: array<string, mixed>, ssl?: ?boolean, write_buffer_size?: int, ssl_method?: int} $config
165+
* @param array{remote_socket?: string|null, timeout?: int, stream_context?: resource, stream_context_options?: array<string, mixed>, stream_context_param?: array<string, mixed>, ssl?: ?bool, write_buffer_size?: int, ssl_method?: int} $config
145166
*
146-
* @return array{remote_socket: string|null, timeout: int, stream_context: resource, stream_context_options: array<string, mixed>, stream_context_param: array<string, mixed>, ssl: ?boolean, write_buffer_size: int, ssl_method: int}
167+
* @return array{remote_socket: string|null, timeout: int, stream_context: resource, stream_context_options: array<string, mixed>, stream_context_param: array<string, mixed>, ssl: ?bool, write_buffer_size: int, ssl_method: int}
147168
*/
148169
protected function configure(array $config = [])
149170
{
@@ -167,7 +188,12 @@ protected function configure(array $config = [])
167188
$resolver->setAllowedTypes('stream_context', 'resource');
168189
$resolver->setAllowedTypes('ssl', ['bool', 'null']);
169190

170-
return $resolver->resolve($config);
191+
$configuration = $resolver->resolve($config);
192+
if ($configuration['ssl'] && !function_exists('openssl_error_string')) {
193+
throw new InvalidOptionsException('You can not enable ssl when ext-openssl is not installed');
194+
}
195+
196+
return $configuration;
171197
}
172198

173199
/**

src/ResponseReader.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ protected function readResponse(RequestInterface $request, $socket): ResponseInt
3939

4040
$metadatas = stream_get_meta_data($socket);
4141

42-
if (array_key_exists('timed_out', $metadatas) && true === $metadatas['timed_out']) {
42+
if ($metadatas['timed_out']) {
4343
throw new TimeoutException('Error while reading response, stream timed out', $request, null);
4444
}
4545
$header = array_shift($headers);

tests/SocketHttpClientTest.php

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,18 @@
1010

1111
class SocketHttpClientTest extends BaseTestCase
1212
{
13-
public function createClient($options = [])
13+
public function createClient($options = []): HttpMethodsClient
1414
{
1515
return new HttpMethodsClient(new SocketHttpClient($options), new Psr17Factory());
1616
}
1717

18-
public function testTcpSocketDomain()
18+
public function testTcpSocketDomain(): void
1919
{
2020
$this->startServer('tcp-server');
2121
$client = $this->createClient(['remote_socket' => '127.0.0.1:19999']);
2222
$response = $client->get('/', []);
2323

24-
$this->assertEquals(200, $response->getStatusCode());
24+
$this->assertSame(200, $response->getStatusCode());
2525
}
2626

2727
public function testNoRemote(): void
@@ -37,7 +37,7 @@ public function testRemoteInUri(): void
3737
$client = $this->createClient();
3838
$response = $client->get('http://127.0.0.1:19999/', []);
3939

40-
$this->assertEquals(200, $response->getStatusCode());
40+
$this->assertSame(200, $response->getStatusCode());
4141
}
4242

4343
public function testRemoteInHostHeader(): void
@@ -46,8 +46,7 @@ public function testRemoteInHostHeader(): void
4646
$client = $this->createClient();
4747
$response = $client->get('/', ['Host' => '127.0.0.1:19999']);
4848

49-
$this->assertInstanceOf('Psr\Http\Message\ResponseInterface', $response);
50-
$this->assertEquals(200, $response->getStatusCode());
49+
$this->assertSame(200, $response->getStatusCode());
5150
}
5251

5352
public function testBrokenSocket(): void
@@ -71,10 +70,9 @@ public function testSslRemoteInUri(): void
7170
],
7271
],
7372
]);
74-
$response = $client->get('/', []);
73+
$response = $client->get('/');
7574

76-
$this->assertInstanceOf('Psr\Http\Message\ResponseInterface', $response);
77-
$this->assertEquals(200, $response->getStatusCode());
75+
$this->assertSame(200, $response->getStatusCode());
7876
}
7977

8078
public function testUnixSocketDomain(): void
@@ -86,7 +84,7 @@ public function testUnixSocketDomain(): void
8684
]);
8785
$response = $client->get('/', []);
8886

89-
$this->assertEquals(200, $response->getStatusCode());
87+
$this->assertSame(200, $response->getStatusCode());
9088
}
9189

9290
public function testNetworkExceptionOnConnectError(): void
@@ -112,7 +110,7 @@ public function testSslConnection()
112110
]);
113111
$response = $client->get('/', []);
114112

115-
$this->assertEquals(200, $response->getStatusCode());
113+
$this->assertSame(200, $response->getStatusCode());
116114
}
117115

118116
public function testSslConnectionWithClientCertificate(): void
@@ -132,7 +130,7 @@ public function testSslConnectionWithClientCertificate(): void
132130
]);
133131
$response = $client->get('/', []);
134132

135-
$this->assertEquals(200, $response->getStatusCode());
133+
$this->assertSame(200, $response->getStatusCode());
136134
}
137135

138136
public function testInvalidSslConnectionWithClientCertificate(): void

tests/server/ssl/file.srl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
34
1+
3A

tests/server/tcp-server.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55
$socketServer = stream_socket_server('127.0.0.1:19999');
66
$client = stream_socket_accept($socketServer);
77

8-
fwrite($client, str_replace("\n", "\r\n", <<<EOR
8+
fwrite($client, str_replace(
9+
"\n",
10+
"\r\n",
11+
<<<EOR
912
HTTP/1.1 200 OK
1013
Content-Type: text/plain
1114

tests/server/tcp-ssl-server-client.php

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,27 @@
2020
// Verify client certificate
2121
$name = null;
2222

23-
if (isset(stream_context_get_options($context)['ssl']['peer_certificate'])) {
24-
$client_cert = stream_context_get_options($context)['ssl']['peer_certificate'];
23+
if (isset(stream_context_get_options($client)['ssl']['peer_certificate'])) {
24+
$client_cert = stream_context_get_options($client)['ssl']['peer_certificate'];
2525
$name = openssl_x509_parse($client_cert)['subject']['CN'];
2626
}
2727

2828
if ('socket-adapter-client' == $name) {
29-
fwrite($client, str_replace("\n", "\r\n", <<<EOR
29+
fwrite($client, str_replace(
30+
"\n",
31+
"\r\n",
32+
<<<EOR
3033
HTTP/1.1 200 OK
3134
Content-Type: text/plain
3235
3336
Test
3437
EOR
3538
));
3639
} else {
37-
fwrite($client, str_replace("\n", "\r\n", <<<EOR
40+
fwrite($client, str_replace(
41+
"\n",
42+
"\r\n",
43+
<<<EOR
3844
HTTP/1.1 403 Invalid ssl certificate
3945
Content-Type: text/plain
4046

tests/server/tcp-ssl-server.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,21 @@
1414
$client = stream_socket_accept($socketServer);
1515
stream_set_blocking($client, true);
1616
if (@stream_socket_enable_crypto($client, true, STREAM_CRYPTO_METHOD_TLSv1_2_SERVER)) {
17-
fwrite($client, str_replace("\n", "\r\n", <<<EOR
17+
fwrite($client, str_replace(
18+
"\n",
19+
"\r\n",
20+
<<<EOR
1821
HTTP/1.1 200 OK
1922
Content-Type: text/plain
2023
2124
Test
2225
EOR
2326
));
2427
} else {
25-
fwrite($client, str_replace("\n", "\r\n", <<<EOR
28+
fwrite($client, str_replace(
29+
"\n",
30+
"\r\n",
31+
<<<EOR
2632
HTTP/1.1 400 Bad Request
2733
Content-Type: text/plain
2834

0 commit comments

Comments
 (0)