Skip to content

Commit 086ca1b

Browse files
Merge branch '4.3'
* 4.3: [HttpClient] make $response->getInfo('debug') return extended logs about the HTTP transaction fix typo Fixes a small doc blocks syntax error Small grammar mistake in documentation [Messenger] Use real memory usage for --memory-limit [Workflow] Do not trigger extra guard
2 parents f0a14b1 + 7aeb6f5 commit 086ca1b

File tree

8 files changed

+100
-9
lines changed

8 files changed

+100
-9
lines changed

src/Symfony/Component/HttpClient/NativeHttpClient.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ public function request(string $method, string $url, array $options = []): Respo
108108
'size_body' => \strlen($options['body']),
109109
'primary_ip' => '',
110110
'primary_port' => 'http:' === $url['scheme'] ? 80 : 443,
111+
'debug' => \extension_loaded('curl') ? '' : "* Enable the curl extension for better performance\n",
111112
];
112113

113114
if ($onProgress = $options['on_progress']) {
@@ -139,6 +140,8 @@ public function request(string $method, string $url, array $options = []): Respo
139140
$info['size_download'] = $dlNow;
140141
} elseif (STREAM_NOTIFY_CONNECT === $code) {
141142
$info['connect_time'] += $now - $info['fopen_time'];
143+
$info['debug'] .= $info['request_header'];
144+
unset($info['request_header']);
142145
} else {
143146
return;
144147
}
@@ -160,13 +163,16 @@ public function request(string $method, string $url, array $options = []): Respo
160163
$options['request_headers'][] = 'host: '.$host.$port;
161164
}
162165

166+
if (!isset($options['headers']['user-agent'])) {
167+
$options['request_headers'][] = 'user-agent: Symfony HttpClient/Native';
168+
}
169+
163170
$context = [
164171
'http' => [
165172
'protocol_version' => $options['http_version'] ?: '1.1',
166173
'method' => $method,
167174
'content' => $options['body'],
168175
'ignore_errors' => true,
169-
'user_agent' => 'Symfony HttpClient/Native',
170176
'curl_verify_ssl_peer' => $options['verify_peer'],
171177
'curl_verify_ssl_host' => $options['verify_host'],
172178
'auto_decode' => false, // Disable dechunk filter, it's incompatible with stream_select()
@@ -296,6 +302,7 @@ private static function dnsResolve(array $url, NativeClientState $multi, array &
296302
$host = parse_url($url['authority'], PHP_URL_HOST);
297303

298304
if (null === $ip = $multi->dnsCache[$host] ?? null) {
305+
$info['debug'] .= "* Hostname was NOT found in DNS cache\n";
299306
$now = microtime(true);
300307

301308
if (!$ip = gethostbynamel($host)) {
@@ -304,6 +311,9 @@ private static function dnsResolve(array $url, NativeClientState $multi, array &
304311

305312
$info['namelookup_time'] += microtime(true) - $now;
306313
$multi->dnsCache[$host] = $ip = $ip[0];
314+
$info['debug'] .= "* Added {$host}:0:{$ip} to DNS cache\n";
315+
} else {
316+
$info['debug'] .= "* Hostname was found in DNS cache\n";
307317
}
308318

309319
$info['primary_ip'] = $ip;

src/Symfony/Component/HttpClient/Response/CurlResponse.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ final class CurlResponse implements ResponseInterface
2828

2929
private static $performing = false;
3030
private $multi;
31+
private $debugBuffer;
3132

3233
/**
3334
* @internal
@@ -38,6 +39,9 @@ public function __construct(CurlClientState $multi, $ch, array $options = null,
3839

3940
if (\is_resource($ch)) {
4041
$this->handle = $ch;
42+
$this->debugBuffer = fopen('php://temp', 'w+');
43+
curl_setopt($ch, CURLOPT_VERBOSE, true);
44+
curl_setopt($ch, CURLOPT_STDERR, $this->debugBuffer);
4145
} else {
4246
$this->info['url'] = $ch;
4347
$ch = $this->handle;
@@ -143,6 +147,13 @@ public function getInfo(string $type = null)
143147
{
144148
if (!$info = $this->finalInfo) {
145149
self::perform($this->multi);
150+
151+
if ('debug' === $type) {
152+
rewind($this->debugBuffer);
153+
154+
return stream_get_contents($this->debugBuffer);
155+
}
156+
146157
$info = array_merge($this->info, curl_getinfo($this->handle));
147158
$info['url'] = $this->info['url'] ?? $info['url'];
148159
$info['redirect_url'] = $this->info['redirect_url'] ?? null;
@@ -154,6 +165,10 @@ public function getInfo(string $type = null)
154165
}
155166

156167
if (!\in_array(curl_getinfo($this->handle, CURLINFO_PRIVATE), ['headers', 'content'], true)) {
168+
rewind($this->debugBuffer);
169+
$info['debug'] = stream_get_contents($this->debugBuffer);
170+
fclose($this->debugBuffer);
171+
$this->debugBuffer = null;
157172
$this->finalInfo = $info;
158173
}
159174
}

src/Symfony/Component/HttpClient/Response/NativeResponse.php

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ final class NativeResponse implements ResponseInterface
3434
private $buffer;
3535
private $inflate;
3636
private $multi;
37+
private $debugBuffer;
3738

3839
/**
3940
* @internal
@@ -76,12 +77,19 @@ public function getInfo(string $type = null)
7677
{
7778
if (!$info = $this->finalInfo) {
7879
self::perform($this->multi);
80+
81+
if ('debug' === $type) {
82+
return $this->info['debug'];
83+
}
84+
7985
$info = $this->info;
8086
$info['url'] = implode('', $info['url']);
81-
unset($info['fopen_time'], $info['size_body']);
87+
unset($info['fopen_time'], $info['size_body'], $info['request_header']);
8288

8389
if (null === $this->buffer) {
8490
$this->finalInfo = $info;
91+
} else {
92+
unset($info['debug']);
8593
}
8694
}
8795

@@ -112,10 +120,23 @@ private function open(): void
112120
$url = $this->url;
113121

114122
while (true) {
123+
$context = stream_context_get_options($this->context);
124+
125+
if ($proxy = $context['http']['proxy'] ?? null) {
126+
$this->info['debug'] .= "* Establish HTTP proxy tunnel to {$proxy}\n";
127+
$this->info['request_header'] = $url;
128+
} else {
129+
$this->info['debug'] .= "* Trying {$this->info['primary_ip']}...\n";
130+
$this->info['request_header'] = $this->info['url']['path'].$this->info['url']['query'];
131+
}
132+
133+
$this->info['request_header'] = sprintf("> %s %s HTTP/%s \r\n", $context['http']['method'], $this->info['request_header'], $context['http']['protocol_version']);
134+
$this->info['request_header'] .= implode("\r\n", $context['http']['header'])."\r\n\r\n";
135+
115136
// Send request and follow redirects when needed
116137
$this->info['fopen_time'] = microtime(true);
117138
$this->handle = $h = fopen($url, 'r', false, $this->context);
118-
self::addResponseHeaders($http_response_header, $this->info, $this->headers);
139+
self::addResponseHeaders($http_response_header, $this->info, $this->headers, $this->info['debug']);
119140
$url = ($this->resolveRedirect)($this->multi, $this->headers['location'][0] ?? null, $this->context);
120141

121142
if (null === $url) {
@@ -136,7 +157,6 @@ private function open(): void
136157
}
137158

138159
stream_set_blocking($h, false);
139-
$context = stream_context_get_options($this->context);
140160
$this->context = $this->resolveRedirect = null;
141161

142162
if (isset($context['ssl']['peer_certificate_chain'])) {

src/Symfony/Component/HttpClient/Response/ResponseTrait.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,19 +189,25 @@ abstract protected static function perform(ClientState $multi, array &$responses
189189
*/
190190
abstract protected static function select(ClientState $multi, float $timeout): int;
191191

192-
private static function addResponseHeaders(array $responseHeaders, array &$info, array &$headers): void
192+
private static function addResponseHeaders(array $responseHeaders, array &$info, array &$headers, string &$debug = ''): void
193193
{
194194
foreach ($responseHeaders as $h) {
195195
if (11 <= \strlen($h) && '/' === $h[4] && preg_match('#^HTTP/\d+(?:\.\d+)? ([12345]\d\d) .*#', $h, $m)) {
196-
$headers = [];
196+
if ($headers) {
197+
$debug .= "< \r\n";
198+
$headers = [];
199+
}
197200
$info['http_code'] = (int) $m[1];
198201
} elseif (2 === \count($m = explode(':', $h, 2))) {
199202
$headers[strtolower($m[0])][] = ltrim($m[1]);
200203
}
201204

205+
$debug .= "< {$h}\r\n";
202206
$info['response_headers'][] = $h;
203207
}
204208

209+
$debug .= "< \r\n";
210+
205211
if (!$info['http_code']) {
206212
throw new TransportException('Invalid or missing HTTP status line.');
207213
}

src/Symfony/Component/HttpFoundation/Request.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1907,7 +1907,7 @@ private function setPhpDefaultLocale(string $locale)
19071907
}
19081908
}
19091909

1910-
/*
1910+
/**
19111911
* Returns the prefix as encoded in the string when the string starts with
19121912
* the given prefix, false otherwise.
19131913
*

src/Symfony/Component/HttpKernel/Controller/ControllerResolverInterface.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ interface ControllerResolverInterface
2929
* As several resolvers can exist for a single application, a resolver must
3030
* return false when it is not able to determine the controller.
3131
*
32-
* The resolver must only throw an exception when it should be able to load
32+
* The resolver must only throw an exception when it should be able to load a
3333
* controller but cannot because of some errors made by the developer.
3434
*
3535
* @return callable|false A PHP callable representing the Controller,

src/Symfony/Component/HttpKernel/EventListener/FragmentListener.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
* All URL paths starting with /_fragment are handled as
2525
* content fragments by this listener.
2626
*
27-
* If throws an AccessDeniedHttpException exception if the request
27+
* Throws an AccessDeniedHttpException exception if the request
2828
* is not signed or if it is not an internal sub-request.
2929
*
3030
* @author Fabien Potencier <[email protected]>

src/Symfony/Component/Workflow/Tests/WorkflowTest.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,46 @@ public function testApplyWithEventDispatcher()
419419
$this->assertSame($eventNameExpected, $eventDispatcher->dispatchedEvents);
420420
}
421421

422+
public function testApplyDoesNotTriggerExtraGuardWithEventDispatcher()
423+
{
424+
$transitions[] = new Transition('a-b', 'a', 'b');
425+
$transitions[] = new Transition('a-c', 'a', 'c');
426+
$definition = new Definition(['a', 'b', 'c'], $transitions);
427+
428+
$subject = new Subject();
429+
$eventDispatcher = new EventDispatcherMock();
430+
$workflow = new Workflow($definition, new MultipleStateMarkingStore(), $eventDispatcher, 'workflow_name');
431+
432+
$eventNameExpected = [
433+
'workflow.entered',
434+
'workflow.workflow_name.entered',
435+
'workflow.guard',
436+
'workflow.workflow_name.guard',
437+
'workflow.workflow_name.guard.a-b',
438+
'workflow.leave',
439+
'workflow.workflow_name.leave',
440+
'workflow.workflow_name.leave.a',
441+
'workflow.transition',
442+
'workflow.workflow_name.transition',
443+
'workflow.workflow_name.transition.a-b',
444+
'workflow.enter',
445+
'workflow.workflow_name.enter',
446+
'workflow.workflow_name.enter.b',
447+
'workflow.entered',
448+
'workflow.workflow_name.entered',
449+
'workflow.workflow_name.entered.b',
450+
'workflow.completed',
451+
'workflow.workflow_name.completed',
452+
'workflow.workflow_name.completed.a-b',
453+
'workflow.announce',
454+
'workflow.workflow_name.announce',
455+
];
456+
457+
$marking = $workflow->apply($subject, 'a-b');
458+
459+
$this->assertSame($eventNameExpected, $eventDispatcher->dispatchedEvents);
460+
}
461+
422462
public function testApplyWithContext()
423463
{
424464
$definition = $this->createComplexWorkflowDefinition();

0 commit comments

Comments
 (0)