Gateway.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. <?php
  2. /**
  3. * This file is part of amfPHP
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the license that is bundled
  8. * with this package in the file license.txt.
  9. */
  10. /**
  11. * where everything comes together in amfphp.
  12. * The class used for the entry point of a remoting call
  13. *
  14. * @package Amfphp_Core
  15. * @author Ariel Sommeria-klein
  16. */
  17. class Amfphp_Core_Gateway
  18. {
  19. /**
  20. * filter just after plugin init. Use this to add a service folder for a plugin
  21. * @param array serviceFolders array of absolute paths
  22. */
  23. const FILTER_SERVICE_FOLDER_PATHS = 'FILTER_SERVICE_FOLDER_PATHS';
  24. /**
  25. * filter just after plugin init. Use this to add a service for a plugin when a service folder isn't enough
  26. * @param array serviceNames2ClassFindInfo array of ClassFindInfo. Key is the service nane
  27. */
  28. const FILTER_SERVICE_NAMES_2_CLASS_FIND_INFO = 'FILTER_SERVICE_NAMES_2_CLASS_FIND_INFO';
  29. /**
  30. * filter called when the serialized request comes in.
  31. * @todo this filter only allows manipulation of raw post data, and is as such a bit misleading. Maybe rename and do filters for GET and POST
  32. * @param String $rawData the raw http data
  33. */
  34. const FILTER_SERIALIZED_REQUEST = 'FILTER_SERIALIZED_REQUEST';
  35. /**
  36. * filter called to allow a plugin to override the default amf deserializer.
  37. * Plugin should return a Amfphp_Core_Common_IDeserializer if it recognizes the content type
  38. * @param Amfphp_Core_Common_IDeserializer $deserializer the deserializer. null at call in gateway.
  39. * @param String $contentType
  40. */
  41. const FILTER_DESERIALIZER = 'FILTER_DESERIALIZER';
  42. /**
  43. * filter called after the request is deserialized. The callee can modify the data and return it.
  44. * @param mixed $deserializedRequest
  45. */
  46. const FILTER_DESERIALIZED_REQUEST = 'FILTER_DESERIALIZED_REQUEST';
  47. /**
  48. * filter called to allow a plugin to override the default amf deserialized request handler.
  49. * Plugin should return a Amfphp_Core_Common_IDeserializedRequestHandler if it recognizes the request
  50. * @param Amfphp_Core_Common_IDeserializedRequestHandler $deserializedRequestHandler null at call in gateway.
  51. * @param String $contentType
  52. */
  53. const FILTER_DESERIALIZED_REQUEST_HANDLER = 'FILTER_DESERIALIZED_REQUEST_HANDLER';
  54. /**
  55. * filter called when the response is ready but not yet serialized. The callee can modify the data and return it.
  56. * @param $deserializedResponse
  57. */
  58. const FILTER_DESERIALIZED_RESPONSE = 'FILTER_DESERIALIZED_RESPONSE';
  59. /**
  60. * filter called to allow a plugin to override the default amf exception handler.
  61. * If the plugin takes over the handling of the request message,
  62. * it must set this to a proper Amfphp_Core_Common_IExceptionHandler
  63. * @param Amfphp_Core_Common_IExceptionHandler $exceptionHandler. null at call in gateway.
  64. * @param String $contentType
  65. */
  66. const FILTER_EXCEPTION_HANDLER = 'FILTER_EXCEPTION_HANDLER';
  67. /**
  68. * filter called to allow a plugin to override the default amf serializer.
  69. * @param Amfphp_Core_Common_ISerializer $serializer the serializer. null at call in gateway.
  70. * @param String $contentType
  71. * Plugin sets to a Amfphp_Core_Common_ISerializer if it recognizes the content type
  72. */
  73. const FILTER_SERIALIZER = 'FILTER_SERIALIZER';
  74. /**
  75. * filter called when the packet response is ready and serialized.
  76. * @param String $rawData the raw http data
  77. */
  78. const FILTER_SERIALIZED_RESPONSE = 'FILTER_SERIALIZED_RESPONSE';
  79. /**
  80. * filter called to get the headers
  81. * @param array $headers an associative array of headers. For example array('Content-Type' => 'application/x-amf')
  82. * @param String $contentType
  83. */
  84. const FILTER_HEADERS = 'FILTER_HEADERS';
  85. /**
  86. * filter Vo Converter
  87. * note: this has nothing to do with the gateway. Filter definitions should one day be centralized in an independant place.
  88. * @param Amfphp_Core_Common_IVoConverter
  89. */
  90. const FILTER_VO_CONVERTER = 'FILTER_VO_CONVERTER';
  91. /**
  92. * config.
  93. * @var Amfphp_Core_Config
  94. */
  95. protected $config;
  96. /**
  97. * typically the $_GET array.
  98. * @var array
  99. */
  100. protected $getData;
  101. /**
  102. * typically the $_POST array.
  103. * @var array
  104. */
  105. protected $postData;
  106. /**
  107. * the content type. For example for amf, application/x-amf
  108. * @var String
  109. */
  110. protected $contentType;
  111. /**
  112. * the serialized request
  113. * @var String
  114. */
  115. protected $rawInputData;
  116. /**
  117. * the serialized response
  118. * @var String
  119. */
  120. protected $rawOutputData;
  121. /**
  122. *
  123. */
  124. /**
  125. * constructor
  126. * @param array $getData typically the $_GET array.
  127. * @param array $postData typically the $_POST array.
  128. * @param String $rawInputData
  129. * @param String $contentType
  130. * @param Amfphp_Core_Config $config optional. The default config object will be used if null
  131. */
  132. public function __construct(array $getData, array $postData, $rawInputData, $contentType, Amfphp_Core_Config $config = null)
  133. {
  134. $this->getData = $getData;
  135. $this->postData = $postData;
  136. $this->rawInputData = $rawInputData;
  137. $this->contentType = $contentType;
  138. if ($config) {
  139. $this->config = $config;
  140. } else {
  141. $this->config = new Amfphp_Core_Config();
  142. }
  143. //check for deprecated config settings. replace "true" by "false" if you want to keep this around, or simply delete once your upgrade works
  144. if (true) {
  145. if (isset($this->config->serviceFolderPaths)) {
  146. throw new Exception('In the Amfphp config, serviceFolderPaths have been renamed to serviceFolders. See http://www.silexlabs.org/amfphp/documentation/upgrading-from-2-0-x-and-2-1-x-to-2-2/');
  147. }
  148. if (isset($this->config->pluginsConfig['AmfphpCustomClassConverter'])) {
  149. throw new Exception('The AmfphpCustomClassConverter has been renamed to AmfphpVoConverter. Please update your config accordingly. See http://www.silexlabs.org/amfphp/documentation/upgrading-from-2-0-x-and-2-1-x-to-2-2/');
  150. }
  151. if (isset($this->config->pluginsConfig['AmfphpVoConverter'])) {
  152. $voConverterConfig = $this->config->pluginsConfig['AmfphpVoConverter'];
  153. if (isset($voConverterConfig['customClassFolderPaths']) || isset($voConverterConfig['voFolderPaths'])) {
  154. throw new Exception('The AmfphpVoConverter folder info is to be set in "voFolderPaths" . Please update your config accordingly. See http://www.silexlabs.org/amfphp/documentation/upgrading-from-2-0-x-and-2-1-x-to-2-2/');
  155. }
  156. }
  157. }
  158. }
  159. /**
  160. * The service method runs the gateway application. It deserializes the raw data passed into the constructor as an Amfphp_Core_Amf_Packet, handles the headers,
  161. * handles the messages as requests to services, and returns the responses from the services
  162. * It does not however handle output headers, gzip compression, etc. that is the job of the calling script
  163. *
  164. * @return <String> the serialized data
  165. */
  166. public function service()
  167. {
  168. $filterManager = Amfphp_Core_FilterManager::getInstance();
  169. $deserializedResponse = null;
  170. try {
  171. Amfphp_Core_PluginManager::getInstance()->loadPlugins($this->config->pluginsFolders, $this->config->pluginsConfig, $this->config->sharedConfig, $this->config->disabledPlugins);
  172. $defaultHandler = new Amfphp_Core_Amf_Handler($this->config->sharedConfig);
  173. //filter service folder paths
  174. $this->config->serviceFolders = $filterManager->callFilters(self::FILTER_SERVICE_FOLDER_PATHS, $this->config->serviceFolders);
  175. //filter service names 2 class find info
  176. $this->config->serviceNames2ClassFindInfo = $filterManager->callFilters(self::FILTER_SERVICE_NAMES_2_CLASS_FIND_INFO, $this->config->serviceNames2ClassFindInfo);
  177. //filter serialized request
  178. $this->rawInputData = $filterManager->callFilters(self::FILTER_SERIALIZED_REQUEST, $this->rawInputData);
  179. //filter deserializer
  180. $deserializer = $filterManager->callFilters(self::FILTER_DESERIALIZER, $defaultHandler, $this->contentType);
  181. //deserialize
  182. $deserializedRequest = $deserializer->deserialize($this->getData, $this->postData, $this->rawInputData);
  183. //filter deserialized request
  184. $deserializedRequest = $filterManager->callFilters(self::FILTER_DESERIALIZED_REQUEST, $deserializedRequest);
  185. //create service router
  186. $serviceRouter = new Amfphp_Core_Common_ServiceRouter($this->config->serviceFolders, $this->config->serviceNames2ClassFindInfo, $this->config->checkArgumentCount);
  187. //filter deserialized request handler
  188. $deserializedRequestHandler = $filterManager->callFilters(self::FILTER_DESERIALIZED_REQUEST_HANDLER, $defaultHandler, $this->contentType);
  189. //handle request
  190. $deserializedResponse = $deserializedRequestHandler->handleDeserializedRequest($deserializedRequest, $serviceRouter);
  191. } catch (Exception $exception) {
  192. //filter exception handler
  193. $exceptionHandler = $filterManager->callFilters(self::FILTER_EXCEPTION_HANDLER, $defaultHandler, $this->contentType);
  194. //handle exception
  195. $deserializedResponse = $exceptionHandler->handleException($exception);
  196. }
  197. //filter deserialized response
  198. $deserializedResponse = $filterManager->callFilters(self::FILTER_DESERIALIZED_RESPONSE, $deserializedResponse);
  199. //filter serializer
  200. $serializer = $filterManager->callFilters(self::FILTER_SERIALIZER, $defaultHandler, $this->contentType);
  201. //serialize
  202. $this->rawOutputData = $serializer->serialize($deserializedResponse);
  203. //filter serialized response
  204. $this->rawOutputData = $filterManager->callFilters(self::FILTER_SERIALIZED_RESPONSE, $this->rawOutputData);
  205. return $this->rawOutputData;
  206. }
  207. /**
  208. * get the response headers. Creates an associative array of headers, then filters them, then returns an array of strings
  209. * @return array
  210. */
  211. public function getResponseHeaders()
  212. {
  213. $filterManager = Amfphp_Core_FilterManager::getInstance();
  214. $headers = array('Content-Type' => $this->contentType);
  215. $headers = $filterManager->callFilters(self::FILTER_HEADERS, $headers, $this->contentType);
  216. $ret = array();
  217. foreach ($headers as $key => $value) {
  218. $ret[] = $key . ': ' . $value;
  219. }
  220. return $ret;
  221. }
  222. /**
  223. * helper function for sending gateway data to output stream
  224. */
  225. public function output()
  226. {
  227. $responseHeaders = $this->getResponseHeaders();
  228. foreach ($responseHeaders as $header) {
  229. header($header);
  230. }
  231. echo $this->rawOutputData;
  232. return $this->rawOutputData;
  233. }
  234. }