13
13
14
14
use Psr \Log \AbstractLogger ;
15
15
use Symfony \Component \HttpClient \CurlHttpClient ;
16
+ use Symfony \Component \Process \Exception \ProcessFailedException ;
17
+ use Symfony \Component \Process \Process ;
16
18
use Symfony \Contracts \HttpClient \HttpClientInterface ;
17
19
20
+ /*
21
+ Tests for HTTP2 Push need a recent version of both PHP and curl. This docker command should run them:
22
+ docker run -it --rm -v $(pwd):/app -v /path/to/vulcain:/usr/local/bin/vulcain -w /app php:7.3-alpine ./phpunit src/Symfony/Component/HttpClient/Tests/CurlHttpClientTest.php --filter testHttp2Push
23
+ The vulcain binary can be found at https://github.com/symfony/binary-utils/releases/download/v0.1/vulcain_0.1.3_Linux_x86_64.tar.gz - see https://github.com/dunglas/vulcain for source
24
+ */
25
+
18
26
/**
19
27
* @requires extension curl
20
28
*/
21
29
class CurlHttpClientTest extends HttpClientTestCase
22
30
{
31
+ private static $ vulcainStarted = false ;
32
+
23
33
protected function getHttpClient (string $ testCase ): HttpClientInterface
24
34
{
25
35
return new CurlHttpClient ();
@@ -28,7 +38,81 @@ protected function getHttpClient(string $testCase): HttpClientInterface
28
38
/**
29
39
* @requires PHP 7.2.17
30
40
*/
31
- public function testHttp2Push ()
41
+ public function testHttp2PushVulcain ()
42
+ {
43
+ $ client = $ this ->getVulcainClient ();
44
+ $ logger = new TestLogger ();
45
+ $ client ->setLogger ($ logger );
46
+
47
+ $ responseAsArray = $ client ->request ('GET ' , 'https://127.0.0.1:3000/json ' , [
48
+ 'headers ' => [
49
+ 'Preload ' => '/documents/*/id ' ,
50
+ ],
51
+ ])->toArray ();
52
+
53
+ foreach ($ responseAsArray ['documents ' ] as $ document ) {
54
+ $ client ->request ('GET ' , 'https://127.0.0.1:3000 ' .$ document ['id ' ])->toArray ();
55
+ }
56
+
57
+ $ client ->reset ();
58
+
59
+ $ expected = [
60
+ 'Request: "GET https://127.0.0.1:3000/json" ' ,
61
+ 'Queueing pushed response: "https://127.0.0.1:3000/json/1" ' ,
62
+ 'Queueing pushed response: "https://127.0.0.1:3000/json/2" ' ,
63
+ 'Queueing pushed response: "https://127.0.0.1:3000/json/3" ' ,
64
+ 'Response: "200 https://127.0.0.1:3000/json" ' ,
65
+ 'Accepting pushed response: "GET https://127.0.0.1:3000/json/1" ' ,
66
+ 'Response: "200 https://127.0.0.1:3000/json/1" ' ,
67
+ 'Accepting pushed response: "GET https://127.0.0.1:3000/json/2" ' ,
68
+ 'Response: "200 https://127.0.0.1:3000/json/2" ' ,
69
+ 'Accepting pushed response: "GET https://127.0.0.1:3000/json/3" ' ,
70
+ 'Response: "200 https://127.0.0.1:3000/json/3" ' ,
71
+ ];
72
+ $ this ->assertSame ($ expected , $ logger ->logs );
73
+ }
74
+
75
+ /**
76
+ * @requires PHP 7.2.17
77
+ */
78
+ public function testHttp2PushVulcainWithUnusedResponse ()
79
+ {
80
+ $ client = $ this ->getVulcainClient ();
81
+ $ logger = new TestLogger ();
82
+ $ client ->setLogger ($ logger );
83
+
84
+ $ responseAsArray = $ client ->request ('GET ' , 'https://127.0.0.1:3000/json ' , [
85
+ 'headers ' => [
86
+ 'Preload ' => '/documents/*/id ' ,
87
+ ],
88
+ ])->toArray ();
89
+
90
+ $ i = 0 ;
91
+ foreach ($ responseAsArray ['documents ' ] as $ document ) {
92
+ $ client ->request ('GET ' , 'https://127.0.0.1:3000 ' .$ document ['id ' ])->toArray ();
93
+ if (++$ i >= 2 ) {
94
+ break ;
95
+ }
96
+ }
97
+
98
+ $ client ->reset ();
99
+
100
+ $ expected = [
101
+ 'Request: "GET https://127.0.0.1:3000/json" ' ,
102
+ 'Queueing pushed response: "https://127.0.0.1:3000/json/1" ' ,
103
+ 'Queueing pushed response: "https://127.0.0.1:3000/json/2" ' ,
104
+ 'Queueing pushed response: "https://127.0.0.1:3000/json/3" ' ,
105
+ 'Response: "200 https://127.0.0.1:3000/json" ' ,
106
+ 'Accepting pushed response: "GET https://127.0.0.1:3000/json/1" ' ,
107
+ 'Response: "200 https://127.0.0.1:3000/json/1" ' ,
108
+ 'Accepting pushed response: "GET https://127.0.0.1:3000/json/2" ' ,
109
+ 'Response: "200 https://127.0.0.1:3000/json/2" ' ,
110
+ 'Unused pushed response: "https://127.0.0.1:3000/json/3" ' ,
111
+ ];
112
+ $ this ->assertSame ($ expected , $ logger ->logs );
113
+ }
114
+
115
+ private function getVulcainClient (): CurlHttpClient
32
116
{
33
117
if (\PHP_VERSION_ID >= 70300 && \PHP_VERSION_ID < 70304 ) {
34
118
$ this ->markTestSkipped ('PHP 7.3.0 to 7.3.3 don \'t support HTTP/2 PUSH ' );
@@ -38,32 +122,44 @@ public function testHttp2Push()
38
122
$ this ->markTestSkipped ('curl <7.61 is used or it is not compiled with support for HTTP/2 PUSH ' );
39
123
}
40
124
41
- $ logger = new class () extends AbstractLogger {
42
- public $ logs = [];
125
+ $ client = new CurlHttpClient (['verify_peer ' => false , 'verify_host ' => false ]);
43
126
44
- public function log ($ level , $ message , array $ context = []): void
45
- {
46
- $ this ->logs [] = $ message ;
47
- }
48
- };
127
+ if (static ::$ vulcainStarted ) {
128
+ return $ client ;
129
+ }
49
130
50
- $ client = new CurlHttpClient ([], 6 , 2 );
51
- $ client ->setLogger ($ logger );
131
+ if (200 !== $ client ->request ('GET ' , 'http://127.0.0.1:8057/json ' )->getStatusCode ()) {
132
+ $ this ->markTestSkipped ('symfony/http-client-contracts >= 2.0.1 required ' );
133
+ }
52
134
53
- $ index = $ client ->request ('GET ' , 'https://http2.akamai.com/ ' );
54
- $ index ->getContent ();
135
+ $ process = new Process (['vulcain ' ], null , [
136
+ 'DEBUG ' => 1 ,
137
+ 'UPSTREAM ' => 'http://127.0.0.1:8057 ' ,
138
+ 'ADDR ' => ':3000 ' ,
139
+ 'KEY_FILE ' => __DIR__ .'/Fixtures/tls/server.key ' ,
140
+ 'CERT_FILE ' => __DIR__ .'/Fixtures/tls/server.crt ' ,
141
+ ]);
142
+ $ process ->start ();
55
143
56
- $ css = $ client ->request ('GET ' , 'https://http2.akamai.com/resources/push.css ' );
144
+ register_shutdown_function ([$ process , 'stop ' ]);
145
+ sleep ('\\' === \DIRECTORY_SEPARATOR ? 10 : 1 );
57
146
58
- $ css ->getHeaders ();
147
+ if (!$ process ->isRunning ()) {
148
+ throw new ProcessFailedException ($ process );
149
+ }
59
150
60
- $ expected = [
61
- 'Request: "GET https://http2.akamai.com/" ' ,
62
- 'Queueing pushed response: "https://http2.akamai.com/resources/push.css" ' ,
63
- 'Response: "200 https://http2.akamai.com/" ' ,
64
- 'Accepting pushed response: "GET https://http2.akamai.com/resources/push.css" ' ,
65
- 'Response: "200 https://http2.akamai.com/resources/push.css" ' ,
66
- ];
67
- $ this ->assertSame ($ expected , $ logger ->logs );
151
+ static ::$ vulcainStarted = true ;
152
+
153
+ return $ client ;
154
+ }
155
+ }
156
+
157
+ class TestLogger extends AbstractLogger
158
+ {
159
+ public $ logs = [];
160
+
161
+ public function log ($ level , $ message , array $ context = []): void
162
+ {
163
+ $ this ->logs [] = $ message ;
68
164
}
69
165
}
0 commit comments