Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 94167b0

Browse files
committed
Get exception content according to request format
1 parent 4ad54da commit 94167b0

File tree

5 files changed

+183
-2
lines changed

5 files changed

+183
-2
lines changed

src/Symfony/Component/Debug/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ CHANGELOG
88
* added `Exception\FlattenException::getAsString` and
99
`Exception\FlattenException::getTraceAsString` to increase compatibility to php
1010
exception objects
11+
* added `ExceptionHandler::getFormattedContent()` to get the exception content
12+
according to given format (html, json, xml, txt)
1113

1214
4.0.0
1315
-----

src/Symfony/Component/Debug/ExceptionHandler.php

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Symfony\Component\Debug\Exception\FlattenException;
1515
use Symfony\Component\Debug\Exception\OutOfMemoryException;
16+
use Symfony\Component\HttpFoundation\Response;
1617
use Symfony\Component\HttpKernel\Debug\FileLinkFormatter;
1718

1819
/**
@@ -189,6 +190,159 @@ public function sendPhpResponse($exception)
189190
echo $this->decorate($this->getContent($exception), $this->getStylesheet($exception));
190191
}
191192

193+
/**
194+
* Gets the content associated with the given exception.
195+
*
196+
* @param \Exception|FlattenException $exception An \Exception or FlattenException instance
197+
* @param string $format The request format (html, json, xml, txt)
198+
*
199+
* @return string The formatted content as a string
200+
*/
201+
public function getFormattedContent($exception, string $format): string
202+
{
203+
switch ($format) {
204+
case 'json':
205+
return $this->getJson($exception);
206+
case 'xml':
207+
return $this->getXml($exception);
208+
case 'txt':
209+
return $this->getTxt($exception);
210+
default:
211+
return $this->getHtml($exception);
212+
}
213+
}
214+
215+
/**
216+
* Gets the JSON content associated with the given exception.
217+
*
218+
* @param \Exception|FlattenException $exception An \Exception or FlattenException instance
219+
*
220+
* @return string The JSON content as a string
221+
*/
222+
public function getJson($exception): string
223+
{
224+
if (!$exception instanceof FlattenException) {
225+
$exception = FlattenException::create($exception);
226+
}
227+
228+
if (404 === $statusCode = $exception->getStatusCode()) {
229+
$title = 'Not Found';
230+
} elseif (class_exists(Response::class) && isset(Response::$statusTexts[$statusCode])) {
231+
$title = Response::$statusTexts[$statusCode];
232+
} else {
233+
$title = 'Internal Server Error';
234+
}
235+
236+
$content = [
237+
'title' => $title,
238+
'status' => $statusCode,
239+
'detail' => $this->escapeHtml($exception->getMessage()),
240+
];
241+
242+
if ($this->debug) {
243+
$content['exceptions'] = $exception->toArray();
244+
}
245+
246+
return (string) json_encode($content);
247+
}
248+
249+
/**
250+
* Gets the XML content associated with the given exception.
251+
*
252+
* @param \Exception|FlattenException $exception An \Exception or FlattenException instance
253+
*
254+
* @return string The XML content as a string
255+
*/
256+
public function getXml($exception): string
257+
{
258+
if (!$exception instanceof FlattenException) {
259+
$exception = FlattenException::create($exception);
260+
}
261+
262+
if (404 === $statusCode = $exception->getStatusCode()) {
263+
$title = 'Not Found';
264+
} elseif (class_exists(Response::class) && isset(Response::$statusTexts[$statusCode])) {
265+
$title = Response::$statusTexts[$statusCode];
266+
} else {
267+
$title = 'Internal Server Error';
268+
}
269+
$message = $this->escapeHtml($exception->getMessage());
270+
271+
$exceptions = '';
272+
if ($this->debug) {
273+
$exceptions .= '<exceptions>';
274+
foreach ($exception->toArray() as $e) {
275+
$exceptions .= sprintf('<exception class="%s" message="%s"><traces>', $e['class'], $this->escapeHtml($e['message']));
276+
foreach ($e['trace'] as $trace) {
277+
$exceptions .= '<trace>';
278+
if ($trace['function']) {
279+
$exceptions .= sprintf('at %s%s%s(%s) ', $trace['class'], $trace['type'], $trace['function'], strip_tags($this->formatArgs($trace['args'])));
280+
}
281+
if (isset($trace['file'], $trace['line'])) {
282+
$exceptions .= strip_tags($this->formatPath($trace['file'], $trace['line']));
283+
}
284+
$exceptions .= '</trace>';
285+
}
286+
$exceptions .= '</traces></exception>';
287+
}
288+
$exceptions .= '</exceptions>';
289+
}
290+
291+
return <<<EOF
292+
<?xml version="1.0" encoding="{$this->charset}" ?>
293+
<problem xmlns="urn:ietf:rfc:7807">
294+
<title>{$title}</title>
295+
<status>{$statusCode}</status>
296+
<detail>{$message}</detail>
297+
{$exceptions}
298+
</problem>
299+
EOF;
300+
}
301+
302+
/**
303+
* Gets the TXT content associated with the given exception.
304+
*
305+
* @param \Exception|FlattenException $exception An \Exception or FlattenException instance
306+
*
307+
* @return string The TXT content as a string
308+
*/
309+
public function getTxt($exception): string
310+
{
311+
if (!$exception instanceof FlattenException) {
312+
$exception = FlattenException::create($exception);
313+
}
314+
315+
if (404 === $statusCode = $exception->getStatusCode()) {
316+
$title = 'Not Found';
317+
} elseif (class_exists(Response::class) && isset(Response::$statusTexts[$statusCode])) {
318+
$title = Response::$statusTexts[$statusCode];
319+
} else {
320+
$title = 'Internal Server Error';
321+
}
322+
323+
$content = sprintf("[title] %s\n", $title);
324+
$content .= sprintf("[status] %s\n", $statusCode);
325+
$content .= sprintf("[detail] %s\n", $exception->getMessage());
326+
327+
if ($this->debug) {
328+
foreach ($exception->toArray() as $i => $e) {
329+
$content .= sprintf("[%d] %s: %s\n", $i + 1, $e['class'], $e['message']);
330+
331+
foreach ($e['trace'] as $trace) {
332+
if ($trace['function']) {
333+
$content .= sprintf('at %s%s%s(%s) ', $trace['class'], $trace['type'], $trace['function'], strip_tags($this->formatArgs($trace['args'])));
334+
}
335+
if (isset($trace['file'], $trace['line'])) {
336+
$content .= strip_tags($this->formatPath($trace['file'], $trace['line']));
337+
}
338+
$content .= "\n";
339+
}
340+
}
341+
}
342+
343+
return $content;
344+
}
345+
192346
/**
193347
* Gets the full HTML content associated with the given exception.
194348
*

src/Symfony/Component/Debug/Tests/ExceptionHandlerTest.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,4 +139,28 @@ public function testHandleOutOfMemoryException()
139139

140140
$handler->handle($exception);
141141
}
142+
143+
public function testJsonExceptionContent()
144+
{
145+
$handler = new ExceptionHandler(true);
146+
$content = $handler->getJson(new \RuntimeException('Foo'));
147+
148+
$this->assertStringMatchesFormat('{"title":"Internal Server Error","status":500,"detail":"Foo","exceptions":[{"message":"Foo","class":"RuntimeException"%S}]}', $content);
149+
}
150+
151+
public function testXmlExceptionContent()
152+
{
153+
$handler = new ExceptionHandler(true);
154+
$content = $handler->getXml(new \RuntimeException('Foo'));
155+
156+
$this->assertStringMatchesFormat('<?xml version="1.0" encoding="UTF-8" ?>%A<problem xmlns="urn:ietf:rfc:7807">%A<title>Internal Server Error</title>%A<status>500</status>%A<detail>Foo</detail>%A<exceptions><exception class="RuntimeException" message="Foo"><traces><trace>%A', $content);
157+
}
158+
159+
public function testTxtExceptionContent()
160+
{
161+
$handler = new ExceptionHandler(true);
162+
$content = $handler->getTxt(new \RuntimeException('Foo'));
163+
164+
$this->assertStringMatchesFormat("[title] Internal Server Error\n[status] 500\n[detail] Foo\n[1] RuntimeException: Foo\nin ExceptionHandlerTest.php line %A", $content);
165+
}
142166
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,10 +151,10 @@ protected function duplicateRequest(\Exception $exception, Request $request)
151151
{
152152
$attributes = [
153153
'exception' => $exception = FlattenException::create($exception),
154-
'_controller' => $this->controller ?: function () use ($exception) {
154+
'_controller' => $this->controller ?: function () use ($exception, $request) {
155155
$handler = new ExceptionHandler($this->debug, $this->charset, $this->fileLinkFormat);
156156

157-
return new Response($handler->getHtml($exception), $exception->getStatusCode(), $exception->getHeaders());
157+
return new Response($handler->getFormattedContent($exception, $request->getRequestFormat()), $exception->getStatusCode(), $exception->getHeaders());
158158
},
159159
'logger' => $this->logger instanceof DebugLoggerInterface ? $this->logger : null,
160160
];

src/Symfony/Component/HttpKernel/composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
"conflict": {
4949
"symfony/browser-kit": "<4.3",
5050
"symfony/config": "<3.4",
51+
"symfony/debug": "<4.3",
5152
"symfony/dependency-injection": "<4.2",
5253
"symfony/translation": "<4.2",
5354
"symfony/var-dumper": "<4.1.1",

0 commit comments

Comments
 (0)