Response.php 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. <?php
  2. /**
  3. * Web API REST response.
  4. *
  5. * Copyright © Magento, Inc. All rights reserved.
  6. * See COPYING.txt for license details.
  7. */
  8. namespace Magento\Framework\Webapi\Rest;
  9. class Response extends \Magento\Framework\Webapi\Response
  10. {
  11. /**
  12. * @var \Magento\Framework\Webapi\ErrorProcessor
  13. */
  14. protected $_errorProcessor;
  15. /**
  16. * @var \Magento\Framework\Webapi\Rest\Response\RendererInterface
  17. */
  18. protected $_renderer;
  19. /**
  20. * @var \Magento\Framework\App\State
  21. */
  22. protected $_appState;
  23. /**
  24. * Exception stack
  25. * @var \Exception
  26. */
  27. protected $exceptions = [];
  28. /**
  29. * Initialize dependencies.
  30. *
  31. * @param \Magento\Framework\Webapi\Rest\Response\RendererFactory $rendererFactory
  32. * @param \Magento\Framework\Webapi\ErrorProcessor $errorProcessor
  33. * @param \Magento\Framework\App\State $appState
  34. */
  35. public function __construct(
  36. \Magento\Framework\Webapi\Rest\Response\RendererFactory $rendererFactory,
  37. \Magento\Framework\Webapi\ErrorProcessor $errorProcessor,
  38. \Magento\Framework\App\State $appState
  39. ) {
  40. $this->_renderer = $rendererFactory->get();
  41. $this->_errorProcessor = $errorProcessor;
  42. $this->_appState = $appState;
  43. }
  44. /**
  45. * Send response to the client, render exceptions if they are present.
  46. *
  47. * @return void
  48. */
  49. public function sendResponse()
  50. {
  51. try {
  52. if ($this->isException()) {
  53. $this->_renderMessages();
  54. }
  55. parent::sendResponse();
  56. } catch (\Exception $e) {
  57. if ($e instanceof \Magento\Framework\Webapi\Exception) {
  58. // If the server does not support all MIME types accepted by the client it SHOULD send 406.
  59. $httpCode = $e->getHttpCode() ==
  60. \Magento\Framework\Webapi\Exception::HTTP_NOT_ACCEPTABLE ?
  61. \Magento\Framework\Webapi\Exception::HTTP_NOT_ACCEPTABLE :
  62. \Magento\Framework\Webapi\Exception::HTTP_INTERNAL_ERROR;
  63. } else {
  64. $httpCode = \Magento\Framework\Webapi\Exception::HTTP_INTERNAL_ERROR;
  65. }
  66. /** If error was encountered during "error rendering" process then use error renderer. */
  67. $this->_errorProcessor->renderException($e, $httpCode);
  68. }
  69. }
  70. /**
  71. * Generate and set HTTP response code, error messages to Response object.
  72. *
  73. * @return $this
  74. */
  75. protected function _renderMessages()
  76. {
  77. $responseHttpCode = null;
  78. /** @var \Exception $exception */
  79. foreach ($this->getException() as $exception) {
  80. $maskedException = $this->_errorProcessor->maskException($exception);
  81. $messageData = [
  82. 'message' => $maskedException->getMessage(),
  83. ];
  84. if ($maskedException->getErrors()) {
  85. $messageData['errors'] = [];
  86. foreach ($maskedException->getErrors() as $errorMessage) {
  87. $errorData['message'] = $errorMessage->getRawMessage();
  88. $errorData['parameters'] = $errorMessage->getParameters();
  89. $messageData['errors'][] = $errorData;
  90. }
  91. }
  92. if ($maskedException->getCode()) {
  93. $messageData['code'] = $maskedException->getCode();
  94. }
  95. if ($maskedException->getDetails()) {
  96. $messageData['parameters'] = $maskedException->getDetails();
  97. }
  98. if ($this->_appState->getMode() == \Magento\Framework\App\State::MODE_DEVELOPER) {
  99. $messageData['trace'] = $exception instanceof \Magento\Framework\Webapi\Exception
  100. ? $exception->getStackTrace()
  101. : $exception->getTraceAsString();
  102. }
  103. $responseHttpCode = $maskedException->getHttpCode();
  104. }
  105. // set HTTP code of the last error, Content-Type, and all rendered error messages to body
  106. $this->setHttpResponseCode($responseHttpCode);
  107. $this->setMimeType($this->_renderer->getMimeType());
  108. $this->setBody($this->_renderer->render($messageData));
  109. return $this;
  110. }
  111. /**
  112. * Perform rendering of response data.
  113. *
  114. * @param array|int|string|bool|float|null $outputData
  115. * @return $this
  116. */
  117. public function prepareResponse($outputData = null)
  118. {
  119. $this->_render($outputData);
  120. if ($this->getMessages()) {
  121. $this->_render(['messages' => $this->getMessages()]);
  122. }
  123. return $this;
  124. }
  125. /**
  126. * Render data using registered Renderer.
  127. *
  128. * @param array|int|string|bool|float|null $data
  129. * @return void
  130. */
  131. protected function _render($data)
  132. {
  133. $mimeType = $this->_renderer->getMimeType();
  134. $body = $this->_renderer->render($data);
  135. $this->setMimeType($mimeType)->setBody($body);
  136. }
  137. /**
  138. * Register an exception with the response
  139. *
  140. * @param \Exception $e
  141. * @return $this
  142. */
  143. public function setException($e)
  144. {
  145. $this->exceptions[] = $e;
  146. return $this;
  147. }
  148. /**
  149. * Has an exception been registered with the response?
  150. *
  151. * @return boolean
  152. */
  153. public function isException()
  154. {
  155. return !empty($this->exceptions);
  156. }
  157. /**
  158. * Retrieve the exception stack
  159. *
  160. * @return array
  161. */
  162. public function getException()
  163. {
  164. return $this->exceptions;
  165. }
  166. /**
  167. * Does the response object contain an exception of a given type?
  168. *
  169. * @param string $type
  170. * @return boolean
  171. */
  172. public function hasExceptionOfType($type)
  173. {
  174. foreach ($this->exceptions as $e) {
  175. if ($e instanceof $type) {
  176. return true;
  177. }
  178. }
  179. return false;
  180. }
  181. }