Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit0dbe5db

Browse files
committed
feat(profiler): add cURL copy/paste to request tab
1 parenta4a0463 commit0dbe5db

File tree

3 files changed

+94
-0
lines changed

3 files changed

+94
-0
lines changed

‎src/Symfony/Bundle/WebProfilerBundle/CHANGELOG.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ CHANGELOG
77
* Add support for the`QUERY` HTTP method in the profiler
88
* Add support for Server-Sent Events /`EventSource` requests in the debug toolbar
99
* Add support for displaying the application runner class
10+
* Add cURL copy paste button in the Request/Response tab
1011

1112
7.3
1213
---

‎src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/request.html.twig‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,25 @@
232232
<p>No content</p>
233233
</div>
234234
{%endif %}
235+
236+
<h3>Retry command</h3>
237+
{%ifcollector.curlCommand!="" %}
238+
<divclass="sf-tabs">
239+
<divclass="tab">
240+
<h3class="tab-title">cURL</h3>
241+
<divclass="tab-content">
242+
<divclass="card">
243+
<buttonclass="btn btn-sm hidden"title="Copy as cURL"data-clipboard-text="{{collector.curlCommand }}">Copy as cURL</button>
244+
<preclass="break-long-words">{{collector.curlCommand }}</pre>
245+
</div>
246+
</div>
247+
</div>
248+
</div>
249+
{%else %}
250+
<divclass="empty">
251+
<p>No content</p>
252+
</div>
253+
{%endif %}
235254
</div>
236255
</div>
237256

‎src/Symfony/Component/HttpKernel/DataCollector/RequestDataCollector.php‎

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
useSymfony\Component\HttpKernel\Event\ControllerEvent;
2323
useSymfony\Component\HttpKernel\Event\ResponseEvent;
2424
useSymfony\Component\HttpKernel\KernelEvents;
25+
useSymfony\Component\Process\Process;
2526
useSymfony\Component\VarDumper\Cloner\Data;
2627

2728
/**
@@ -112,6 +113,7 @@ public function collect(Request $request, Response $response, ?\Throwable $excep
112113
'controller' =>'n/a',
113114
'locale' =>$request->getLocale(),
114115
'dotenv_vars' =>$dotenvVars,
116+
'curlCommand' =>$this->getCurlCommand(),
115117
];
116118

117119
if (isset($this->data['request_headers']['php-auth-pw'])) {
@@ -495,4 +497,76 @@ private function parseController(array|object|string|null $controller): array|st
495497

496498
return\is_string($controller) ?$controller :'n/a';
497499
}
500+
501+
publicfunctiongetCurlCommand(): ?string
502+
{
503+
if (!isset($this->data['method']) || !isset($this->data['path_info'])) {
504+
returnnull;
505+
}
506+
507+
$command = ['curl','--compressed'];
508+
509+
// Build the full URL
510+
$scheme =$this->data['request_server']['HTTPS'] ??false ?'https' :'http';
511+
$host =$this->data['request_server']['HTTP_HOST'] ??$this->data['request_server']['SERVER_NAME'] ??'localhost';
512+
$url =$scheme .'://' .$host .$this->data['path_info'];
513+
514+
if (!empty($this->data['request_query'])) {
515+
$url .='?' .http_build_query($this->data['request_query']->getValue());
516+
}
517+
518+
// Add HTTP method
519+
$method =$this->data['method'];
520+
if ($method !=='GET') {
521+
$command[] =sprintf('--request %s',$method);
522+
}
523+
524+
$command[] =sprintf('--url %s',escapeshellarg($url));
525+
526+
// Add headers
527+
foreach ($this->data['request_headers']->getValue()as$name =>$value) {
528+
if (is_array($value)) {
529+
$value =implode(',',$value);
530+
}
531+
532+
// Skip certain headers
533+
if (in_array(strtolower($name), ['host','cookie'])) {
534+
continue;
535+
}
536+
537+
$command[] ='--header' .escapeshellarg(ucwords($name,'-') .':' .$value);
538+
}
539+
540+
// Add cookies
541+
if (!empty($this->data['request_cookies']->getValue())) {
542+
$cookies = [];
543+
foreach ($this->data['request_cookies']->getValue()as$name =>$value) {
544+
$cookies[] =$name .'=' .$value;
545+
}
546+
$command[] ='--header' .escapeshellarg('Cookie:' .implode(';',$cookies));
547+
}
548+
549+
// Add body data
550+
$content =$this->data['content'];
551+
if (!empty($content) &&in_array($method, ['POST','PUT','PATCH','DELETE'])) {
552+
$command[] ='--data-raw' .$this->escapePayload($content);
553+
}
554+
555+
returnimplode("\\\n",$command);
556+
}
557+
558+
privatefunctionescapePayload(string$payload):string
559+
{
560+
static$useProcess;
561+
562+
if ($useProcess ??=\function_exists('proc_open') &&class_exists(\Symfony\Component\Process\Process::class)) {
563+
returnsubstr((newProcess(['',$payload]))->getCommandLine(),3);
564+
}
565+
566+
if ('\\' === \DIRECTORY_SEPARATOR) {
567+
return'"' .str_replace('"','""',$payload) .'"';
568+
}
569+
570+
return"'" .str_replace("'","'\\''",$payload) ."'";
571+
}
498572
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp