/** * Extract REST routes from APC cache. * Cache is generated if needed * @return array The route objects */ protected function getCachedRoutes() { $ttl = (int)eZINI::instance( 'rest.ini' )->variable( 'CacheSettings', 'RouteApcCacheTTL' ); if( self::$isRouteCacheCreated === false ) { $options = array( 'ttl' => $ttl ); ezcCacheManager::createCache( self::ROUTE_CACHE_ID, self::ROUTE_CACHE_PATH, 'ezpRestCacheStorageApcCluster', $options ); self::$isRouteCacheCreated = true; } $cache = ezcCacheManager::getCache( self::ROUTE_CACHE_ID ); $cacheKey = self::ROUTE_CACHE_KEY . '_' . ezpRestPrefixFilterInterface::getApiProviderName(); if( ( $prefixedRoutes = $cache->restore( $cacheKey ) ) === false ) { try { $prefixedRoutes = $this->doCreateRoutes(); $cache->store( $cacheKey, $prefixedRoutes ); } catch( Exception $e ) { // Sometimes APC can miss a write. No big deal, just log it. // Cache will be regenerated next time ezpRestDebug::getInstance()->log( $e->getMessage(), ezcLog::ERROR ); } } return $prefixedRoutes; }
/** * Generates an URL back out of a route, including possible arguments * * @param array $arguments */ public function generateUrl(array $arguments = null) { // ezpRestPrefixFilterInterface::getScheme() ==> '/v' $apiPrefix = ezpRestPrefixFilterInterface::getApiPrefix() . '/'; $apiProviderName = ezpRestPrefixFilterInterface::getApiProviderName(); return $apiPrefix . (!$apiProviderName ? '' : $apiProviderName . '/') . 'v' . $this->version . '/' . str_replace($apiPrefix, '', $this->route->generateUrl($arguments)); }
public function createView( ezcMvcRoutingInformation $routeInfo, ezcMvcRequest $request, ezcMvcResult $result ) { $viewController = ezpRestProvider::getProvider( ezpRestPrefixFilterInterface::getApiProviderName() )->getViewController(); $view = $viewController->loadView( $routeInfo, $request, $result ); return $view; }
/** * Creates a new cache storage for a given location through eZ Publish cluster mechanism * Options can contain the 'ttl' ( Time-To-Life ). This is per default set * to 1 day. * @param string $location Path to the cache location inside the cluster * @param array(string=>string) $options Options for the cache. */ public function __construct( $location, $options = array() ) { $apiName = ezpRestPrefixFilterInterface::getApiProviderName(); $apiVersion = ezpRestPrefixFilterInterface::getApiVersion(); $location = eZSys::cacheDirectory().'/rest/'.$location; if( !file_exists( $location ) ) { if( !eZDir::mkdir( $location, false, true ) ) { throw new ezcBaseFilePermissionException( $location, ezcBaseFileException::WRITE, 'Cache location is not writeable.' ); } } parent::__construct( $location ); $this->properties['options'] = new ezpCacheStorageClusterOptions( $options ); }
/** * @group restApplicationCache * @group restCache * @dataProvider cacheIdVariableProvider * @param array $internalVariables * @param array $contentVariables */ public function testGenerateCacheId(array $internalVariables, array $contentVariables) { /* * The cache ID is a MD5 hash and takes into account : * - API Name * - API Version * - Controller class * - Action * - Internal variables (passed parameters, ResponseGroups...) * - Content variables (Translation...) */ $request = new ezpRestRequest(); $request->uri = $this->restINI->variable('System', 'ApiPrefix') . '/test/rest/foo'; $request->variables = $internalVariables; $request->contentVariables = $contentVariables; $request->protocol = 'http-get'; $controller = $this->getTestControllerFromRequest($request); $routingInfos = $controller->getRouter()->getRoutingInformation(); /* * Reproduce the hash algorythm */ $aCacheId = array(ezpRestPrefixFilterInterface::getApiProviderName(), ezpRestPrefixFilterInterface::getApiVersion(), $routingInfos->controllerClass, $routingInfos->action); foreach ($contentVariables + $internalVariables as $name => $val) { if (is_array($val)) { $aCacheId[] = $name . '=' . implode(',', $val); } else { $aCacheId[] = $name . '=' . $val; } } $hashedCacheId = md5(implode('-', $aCacheId)); $refObj = new ReflectionObject($controller); $refMethod = $refObj->getMethod('generateCacheId'); $refMethod->setAccessible(true); self::assertSame($hashedCacheId, $refMethod->invoke($controller), 'Cache ID algo must take into account : API Name, API Version, Controller class, Action, Internal variables, Content variables'); // Compare currently generated hash with the previous one. Must be different static $previousHash; self::assertNotEquals($hashedCacheId, $previousHash, 'Cache IDs must be unique !'); $previousHash = $hashedCacheId; }
/** * Returns base URI with protocol and host (e.g. http://myhost.com/foo/bar) * * @return string */ public function getBaseURI() { $hostUri = $this->getHostURI(); $apiName = ezpRestPrefixFilterInterface::getApiProviderName(); $apiPrefix = eZINI::instance('rest.ini')->variable('System', 'ApiPrefix'); $uri = str_replace($apiPrefix, $apiPrefix . '/' . $apiName, $this->uri); $baseUri = $hostUri . $uri; return $baseUri; }
/** * Generates unique cache ID for current request. * * The cache ID is a MD5 hash and takes into account : * - API Name * - API Version * - Controller class * - Action * - Internal variables (passed parameters, ResponseGroups...) * - Content variables (Translation...) * * @return string */ private function generateCacheId() { $routingInfos = $this->getRouter()->getRoutingInformation(); $aCacheId = array(ezpRestPrefixFilterInterface::getApiProviderName(), ezpRestPrefixFilterInterface::getApiVersion(), $routingInfos->controllerClass, $routingInfos->action); // Add internal variables, caught in the URL. See ezpRestHttpRequestParser::fillVariables() // Also add content variables foreach ($this->request->contentVariables + $this->request->variables as $name => $val) { $aCacheId[] = $name . '=' . (is_array($val) ? implode(',', $val) : $val); } return md5(implode('-', $aCacheId)); }
/** * Generates unique cache ID for current request. * The cache ID is a MD5 hash and takes into account : * - API Name * - API Version * - Controller class * - Action * - Internal variables (passed parameters, ResponseGroups...) * - Content variables (Translation...) * @return string */ private function generateCacheId() { $apiName = ezpRestPrefixFilterInterface::getApiProviderName(); $apiVersion = ezpRestPrefixFilterInterface::getApiVersion(); $routingInfos = $this->getRouter()->getRoutingInformation(); $aCacheId = array( $apiName, $apiVersion, $routingInfos->controllerClass, $routingInfos->action ); // Add internal variables, caught in the URL. See ezpRestHttpRequestParser::fillVariables() // Also add content variables $allInternalVariables = array_merge( $this->request->variables, $this->getAllContentVariables() ); foreach( $allInternalVariables as $name => $val ) { if( is_array( $val ) ) $aCacheId[] = $name.'='.implode( ',', $val ); else $aCacheId[] = $name.'='.$val; } $cacheId = implode( '-', $aCacheId ); return md5( $cacheId ); }
public function createRoutes() { $providerRoutes = ezpRestProvider::getProvider(ezpRestPrefixFilterInterface::getApiProviderName())->getRoutes(); $routes = array(new ezcMvcRailsRoute('/fatal', 'ezpRestErrorController', 'show'), new ezcMvcRailsRoute('/http-basic-auth', 'ezpRestAuthController', 'basicAuth'), new ezcMvcRailsRoute('/login/oauth', 'ezpRestAuthController', 'oauthRequired'), new ezcMvcRailsRoute('/oauth/token', 'ezpRestOauthTokenController', 'handleRequest'), new ezpRestVersionedRoute(new ezcMvcRailsRoute('/foo', 'myController', 'myActionOne'), 1), new ezpRestVersionedRoute(new ezcMvcRailsRoute('/foo', 'myController', 'myActionOneBetter'), 2)); return ezcMvcRouter::prefix('/api', array_merge($providerRoutes, $routes)); }