Gateway.php 11 KB

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