PageRenderTime 44ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/api/Slim/Handlers/Error.php

https://gitlab.com/jatasya/testSlimfrmwk
PHP | 239 lines | 139 code | 31 blank | 69 comment | 14 complexity | b89d1a148091d875b901b91688da417e MD5 | raw file
  1. <?php
  2. /**
  3. * Slim Framework (http://slimframework.com)
  4. *
  5. * @link https://github.com/slimphp/Slim
  6. * @copyright Copyright (c) 2011-2015 Josh Lockhart
  7. * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  8. */
  9. namespace Slim\Handlers;
  10. use Exception;
  11. use Psr\Http\Message\ResponseInterface;
  12. use Psr\Http\Message\ServerRequestInterface;
  13. use Slim\Http\Body;
  14. /**
  15. * Default Slim application error handler
  16. *
  17. * It outputs the error message and diagnostic information in either JSON, XML,
  18. * or HTML based on the Accept header.
  19. */
  20. class Error
  21. {
  22. protected $displayErrorDetails;
  23. /**
  24. * Known handled content types
  25. *
  26. * @var array
  27. */
  28. protected $knownContentTypes = [
  29. 'application/json',
  30. 'application/xml',
  31. 'text/xml',
  32. 'text/html',
  33. ];
  34. /**
  35. * Constructor
  36. *
  37. * @param boolean $displayErrorDetails Set to true to display full details
  38. */
  39. public function __construct($displayErrorDetails = false)
  40. {
  41. $this->displayErrorDetails = (bool)$displayErrorDetails;
  42. }
  43. /**
  44. * Invoke error handler
  45. *
  46. * @param ServerRequestInterface $request The most recent Request object
  47. * @param ResponseInterface $response The most recent Response object
  48. * @param Exception $exception The caught Exception object
  49. *
  50. * @return ResponseInterface
  51. */
  52. public function __invoke(ServerRequestInterface $request, ResponseInterface $response, Exception $exception)
  53. {
  54. $contentType = $this->determineContentType($request);
  55. switch ($contentType) {
  56. case 'application/json':
  57. $output = $this->renderJsonErrorMessage($exception);
  58. break;
  59. case 'text/xml':
  60. case 'application/xml':
  61. $output = $this->renderXmlErrorMessage($exception);
  62. break;
  63. case 'text/html':
  64. $output = $this->renderHtmlErrorMessage($exception);
  65. break;
  66. }
  67. $body = new Body(fopen('php://temp', 'r+'));
  68. $body->write($output);
  69. return $response
  70. ->withStatus(500)
  71. ->withHeader('Content-type', $contentType)
  72. ->withBody($body);
  73. }
  74. /**
  75. * Render HTML error page
  76. *
  77. * @param Exception $exception
  78. * @return string
  79. */
  80. protected function renderHtmlErrorMessage(Exception $exception)
  81. {
  82. $title = 'Slim Application Error';
  83. if ($this->displayErrorDetails) {
  84. $html = '<p>The application could not run because of the following error:</p>';
  85. $html .= '<h2>Details</h2>';
  86. $html .= $this->renderHtmlException($exception);
  87. while ($exception = $exception->getPrevious()) {
  88. $html .= '<h2>Previous exception</h2>';
  89. $html .= $this->renderHtmlException($exception);
  90. }
  91. } else {
  92. $html = '<p>A website error has occurred. Sorry for the temporary inconvenience.</p>';
  93. }
  94. $output = sprintf(
  95. "<html><head><meta http-equiv='Content-Type' content='text/html; charset=utf-8'>" .
  96. "<title>%s</title><style>body{margin:0;padding:30px;font:12px/1.5 Helvetica,Arial,Verdana," .
  97. "sans-serif;}h1{margin:0;font-size:48px;font-weight:normal;line-height:48px;}strong{" .
  98. "display:inline-block;width:65px;}</style></head><body><h1>%s</h1>%s</body></html>",
  99. $title,
  100. $title,
  101. $html
  102. );
  103. return $output;
  104. }
  105. /**
  106. * Render exception as HTML.
  107. *
  108. * @param Exception $exception
  109. *
  110. * @return string
  111. */
  112. protected function renderHtmlException(Exception $exception)
  113. {
  114. $html = sprintf('<div><strong>Type:</strong> %s</div>', get_class($exception));
  115. if (($code = $exception->getCode())) {
  116. $html .= sprintf('<div><strong>Code:</strong> %s</div>', $code);
  117. }
  118. if (($message = $exception->getMessage())) {
  119. $html .= sprintf('<div><strong>Message:</strong> %s</div>', htmlentities($message));
  120. }
  121. if (($file = $exception->getFile())) {
  122. $html .= sprintf('<div><strong>File:</strong> %s</div>', $file);
  123. }
  124. if (($line = $exception->getLine())) {
  125. $html .= sprintf('<div><strong>Line:</strong> %s</div>', $line);
  126. }
  127. if (($trace = $exception->getTraceAsString())) {
  128. $html .= '<h2>Trace</h2>';
  129. $html .= sprintf('<pre>%s</pre>', htmlentities($trace));
  130. }
  131. return $html;
  132. }
  133. /**
  134. * Render JSON error
  135. *
  136. * @param Exception $exception
  137. * @return string
  138. */
  139. protected function renderJsonErrorMessage(Exception $exception)
  140. {
  141. $error = [
  142. 'message' => 'Slim Application Error',
  143. ];
  144. if ($this->displayErrorDetails) {
  145. $error['exception'] = [];
  146. do {
  147. $error['exception'][] = [
  148. 'type' => get_class($exception),
  149. 'code' => $exception->getCode(),
  150. 'message' => $exception->getMessage(),
  151. 'file' => $exception->getFile(),
  152. 'line' => $exception->getLine(),
  153. 'trace' => explode("\n", $exception->getTraceAsString()),
  154. ];
  155. } while ($exception = $exception->getPrevious());
  156. }
  157. return json_encode($error, JSON_PRETTY_PRINT);
  158. }
  159. /**
  160. * Render XML error
  161. *
  162. * @param Exception $exception
  163. * @return string
  164. */
  165. protected function renderXmlErrorMessage(Exception $exception)
  166. {
  167. $xml = "<error>\n <message>Slim Application Error</message>\n";
  168. if ($this->displayErrorDetails) {
  169. do {
  170. $xml .= " <exception>\n";
  171. $xml .= " <type>" . get_class($exception) . "</type>\n";
  172. $xml .= " <code>" . $exception->getCode() . "</code>\n";
  173. $xml .= " <message>" . $this->createCdataSection($exception->getMessage()) . "</message>\n";
  174. $xml .= " <file>" . $exception->getFile() . "</file>\n";
  175. $xml .= " <line>" . $exception->getLine() . "</line>\n";
  176. $xml .= " <trace>" . $this->createCdataSection($exception->getTraceAsString()) . "</trace>\n";
  177. $xml .= " </exception>\n";
  178. } while ($exception = $exception->getPrevious());
  179. }
  180. $xml .= "</error>";
  181. return $xml;
  182. }
  183. /**
  184. * Returns a CDATA section with the given content.
  185. *
  186. * @param string $content
  187. * @return string
  188. */
  189. private function createCdataSection($content)
  190. {
  191. return sprintf('<![CDATA[%s]]>', str_replace(']]>', ']]]]><![CDATA[>', $content));
  192. }
  193. /**
  194. * Determine which content type we know about is wanted using Accept header
  195. *
  196. * @param ServerRequestInterface $request
  197. * @return string
  198. */
  199. private function determineContentType(ServerRequestInterface $request)
  200. {
  201. $acceptHeader = $request->getHeaderLine('Accept');
  202. $selectedContentTypes = array_intersect(explode(',', $acceptHeader), $this->knownContentTypes);
  203. if (count($selectedContentTypes)) {
  204. return $selectedContentTypes[0];
  205. }
  206. return 'text/html';
  207. }
  208. }