PageRenderTime 27ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/app/code/core/Mage/Api2/Model/Server.php

https://bitbucket.org/jokusafet/magento2
PHP | 315 lines | 148 code | 30 blank | 137 comment | 11 complexity | e8d4860f75ee093708780162f52c8184 MD5 | raw file
  1. <?php
  2. /**
  3. * Magento
  4. *
  5. * NOTICE OF LICENSE
  6. *
  7. * This source file is subject to the Open Software License (OSL 3.0)
  8. * that is bundled with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://opensource.org/licenses/osl-3.0.php
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@magentocommerce.com so we can send you a copy immediately.
  14. *
  15. * DISCLAIMER
  16. *
  17. * Do not edit or add to this file if you wish to upgrade Magento to newer
  18. * versions in the future. If you wish to customize Magento for your
  19. * needs please refer to http://www.magentocommerce.com for more information.
  20. *
  21. * @category Mage
  22. * @package Mage_Api2
  23. * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com)
  24. * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
  25. */
  26. /**
  27. * API2 Server
  28. *
  29. * @category Mage
  30. * @package Mage_Api2
  31. * @author Magento Core Team <core@magentocommerce.com>
  32. */
  33. class Mage_Api2_Model_Server
  34. {
  35. /**
  36. * Api2 REST type
  37. */
  38. const API_TYPE_REST = 'rest';
  39. /**#@+
  40. * HTTP Response Codes
  41. */
  42. const HTTP_OK = 200;
  43. const HTTP_CREATED = 201;
  44. const HTTP_MULTI_STATUS = 207;
  45. const HTTP_BAD_REQUEST = 400;
  46. const HTTP_UNAUTHORIZED = 401;
  47. const HTTP_FORBIDDEN = 403;
  48. const HTTP_NOT_FOUND = 404;
  49. const HTTP_METHOD_NOT_ALLOWED = 405;
  50. const HTTP_NOT_ACCEPTABLE = 406;
  51. const HTTP_INTERNAL_ERROR = 500;
  52. /**#@- */
  53. /**
  54. * List of api types
  55. *
  56. * @var array
  57. */
  58. protected static $_apiTypes = array(self::API_TYPE_REST);
  59. /**
  60. * @var Mage_Api2_Model_Auth_User_Abstract
  61. */
  62. protected $_authUser;
  63. /**
  64. * Run server
  65. */
  66. public function run()
  67. {
  68. // can not use response object case
  69. try {
  70. /** @var $response Mage_Api2_Model_Response */
  71. $response = Mage::getSingleton('Mage_Api2_Model_Response');
  72. } catch (Exception $e) {
  73. Mage::logException($e);
  74. if (!headers_sent()) {
  75. header('HTTP/1.1 ' . self::HTTP_INTERNAL_ERROR);
  76. }
  77. echo 'Service temporary unavailable';
  78. return;
  79. }
  80. // can not render errors case
  81. try {
  82. /** @var $request Mage_Api2_Model_Request */
  83. $request = Mage::getSingleton('Mage_Api2_Model_Request');
  84. /** @var $renderer Mage_Api2_Model_Renderer_Interface */
  85. $renderer = Mage_Api2_Model_Renderer::factory($request->getAcceptTypes());
  86. } catch (Exception $e) {
  87. Mage::logException($e);
  88. $response->setHttpResponseCode(self::HTTP_INTERNAL_ERROR)
  89. ->setBody('Service temporary unavailable')
  90. ->sendResponse();
  91. return;
  92. }
  93. // default case
  94. try {
  95. /** @var $apiUser Mage_Api2_Model_Auth_User_Abstract */
  96. $apiUser = $this->_authenticate($request);
  97. $this->_route($request)
  98. ->_allow($request, $apiUser)
  99. ->_dispatch($request, $response, $apiUser);
  100. if ($response->getHttpResponseCode() == self::HTTP_CREATED) {
  101. // TODO: Re-factor this after _renderException refactoring
  102. throw new Mage_Api2_Exception('Resource was partially created', self::HTTP_CREATED);
  103. }
  104. //NOTE: At this moment Renderer already could have some content rendered, so we should replace it
  105. if ($response->isException()) {
  106. throw new Mage_Api2_Exception('Unhandled simple errors.', self::HTTP_INTERNAL_ERROR);
  107. }
  108. } catch (Exception $e) {
  109. Mage::logException($e);
  110. $this->_renderException($e, $renderer, $response);
  111. }
  112. $response->sendResponse();
  113. }
  114. /**
  115. * Make internal call to api
  116. *
  117. * @param Mage_Api2_Model_Request $request
  118. * @param Mage_Api2_Model_Response $response
  119. * @return Mage_Api2_Model_Response
  120. */
  121. public function internalCall(Mage_Api2_Model_Request $request, Mage_Api2_Model_Response $response)
  122. {
  123. $apiUser = $this->_getAuthUser();
  124. $this->_route($request)
  125. ->_allow($request, $apiUser)
  126. ->_dispatch($request, $response, $apiUser);
  127. }
  128. /**
  129. * Authenticate user
  130. *
  131. * @throws Exception
  132. * @param Mage_Api2_Model_Request $request
  133. * @return Mage_Api2_Model_Auth_User_Abstract
  134. */
  135. protected function _authenticate(Mage_Api2_Model_Request $request)
  136. {
  137. /** @var $authManager Mage_Api2_Model_Auth */
  138. $authManager = Mage::getModel('Mage_Api2_Model_Auth');
  139. $this->_setAuthUser($authManager->authenticate($request));
  140. return $this->_getAuthUser();
  141. }
  142. /**
  143. * Set auth user
  144. *
  145. * @throws Exception
  146. * @param Mage_Api2_Model_Auth_User_Abstract $authUser
  147. * @return Mage_Api2_Model_Server
  148. */
  149. protected function _setAuthUser(Mage_Api2_Model_Auth_User_Abstract $authUser)
  150. {
  151. $this->_authUser = $authUser;
  152. return $this;
  153. }
  154. /**
  155. * Retrieve existing auth user
  156. *
  157. * @throws Exception
  158. * @return Mage_Api2_Model_Auth_User_Abstract
  159. */
  160. protected function _getAuthUser()
  161. {
  162. if (!$this->_authUser) {
  163. throw new Exception("Mage_Api2_Model_Server::internalCall() seems to be executed "
  164. . "before Mage_Api2_Model_Server::run()");
  165. }
  166. return $this->_authUser;
  167. }
  168. /**
  169. * Set all routes of the given api type to Route object
  170. * Find route that match current URL, set parameters of the route to Request object
  171. *
  172. * @param Mage_Api2_Model_Request $request
  173. * @return Mage_Api2_Model_Server
  174. */
  175. protected function _route(Mage_Api2_Model_Request $request)
  176. {
  177. /** @var $router Mage_Api2_Model_Router */
  178. $router = Mage::getModel('Mage_Api2_Model_Router');
  179. $router->routeApiType($request, true)
  180. ->setRoutes($this->_getConfig()->getRoutes($request->getApiType()))
  181. ->route($request);
  182. return $this;
  183. }
  184. /**
  185. * Global ACL processing
  186. *
  187. * @param Mage_Api2_Model_Request $request
  188. * @param Mage_Api2_Model_Auth_User_Abstract $apiUser
  189. * @return Mage_Api2_Model_Server
  190. * @throws Mage_Api2_Exception
  191. */
  192. protected function _allow(Mage_Api2_Model_Request $request, Mage_Api2_Model_Auth_User_Abstract $apiUser)
  193. {
  194. /** @var $globalAcl Mage_Api2_Model_Acl_Global */
  195. $globalAcl = Mage::getModel('Mage_Api2_Model_Acl_Global');
  196. if (!$globalAcl->isAllowed($apiUser, $request->getResourceType(), $request->getOperation())) {
  197. throw new Mage_Api2_Exception('Access denied', self::HTTP_FORBIDDEN);
  198. }
  199. return $this;
  200. }
  201. /**
  202. * Load class file, instantiate resource class, set parameters to the instance, run resource internal dispatch
  203. * method
  204. *
  205. * @param Mage_Api2_Model_Request $request
  206. * @param Mage_Api2_Model_Response $response
  207. * @param Mage_Api2_Model_Auth_User_Abstract $apiUser
  208. * @return Mage_Api2_Model_Server
  209. */
  210. protected function _dispatch(
  211. Mage_Api2_Model_Request $request,
  212. Mage_Api2_Model_Response $response,
  213. Mage_Api2_Model_Auth_User_Abstract $apiUser
  214. )
  215. {
  216. /** @var $dispatcher Mage_Api2_Model_Dispatcher */
  217. $dispatcher = Mage::getModel('Mage_Api2_Model_Dispatcher');
  218. $dispatcher->setApiUser($apiUser)->dispatch($request, $response);
  219. return $this;
  220. }
  221. /**
  222. * Get api2 config instance
  223. *
  224. * @return Mage_Api2_Model_Config
  225. */
  226. protected function _getConfig()
  227. {
  228. return Mage::getModel('Mage_Api2_Model_Config');
  229. }
  230. /**
  231. * Process thrown exception
  232. * Generate and set HTTP response code, error message to Response object
  233. *
  234. * @param Exception $exception
  235. * @param Mage_Api2_Model_Renderer_Interface $renderer
  236. * @param Mage_Api2_Model_Response $response
  237. * @return Mage_Api2_Model_Server
  238. */
  239. protected function _renderException(Exception $exception, Mage_Api2_Model_Renderer_Interface $renderer,
  240. Mage_Api2_Model_Response $response
  241. ) {
  242. if ($exception instanceof Mage_Api2_Exception && $exception->getCode()) {
  243. $httpCode = $exception->getCode();
  244. } else {
  245. $httpCode = self::HTTP_INTERNAL_ERROR;
  246. }
  247. try {
  248. //add last error to stack
  249. $response->setException($exception);
  250. $messages = array();
  251. /** @var Exception $exception */
  252. foreach ($response->getException() as $exception) {
  253. $message = array('code' => $exception->getCode(), 'message' => $exception->getMessage());
  254. if (Mage::getIsDeveloperMode()) {
  255. $message['trace'] = $exception->getTraceAsString();
  256. }
  257. $messages['messages']['error'][] = $message;
  258. }
  259. //set HTTP Code of last error, Content-Type and Body
  260. $response->setBody($renderer->render($messages));
  261. $response->setHeader('Content-Type', sprintf(
  262. '%s; charset=%s', $renderer->getMimeType(), Mage_Api2_Model_Response::RESPONSE_CHARSET
  263. ));
  264. } catch (Exception $e) {
  265. //tunnelling of 406(Not acceptable) error
  266. $httpCode = $e->getCode() == self::HTTP_NOT_ACCEPTABLE //$e->getCode() can result in one more loop
  267. ? self::HTTP_NOT_ACCEPTABLE // of try..catch
  268. : self::HTTP_INTERNAL_ERROR;
  269. //if error appeared in "error rendering" process then show it in plain text
  270. $response->setBody($e->getMessage());
  271. $response->setHeader('Content-Type', 'text/plain; charset=' . Mage_Api2_Model_Response::RESPONSE_CHARSET);
  272. }
  273. $response->setHttpResponseCode($httpCode);
  274. return $this;
  275. }
  276. /**
  277. * Retrieve api types
  278. *
  279. * @return array
  280. */
  281. public static function getApiTypes()
  282. {
  283. return self::$_apiTypes;
  284. }
  285. }