/** * Find the api method to execute for the requested Url */ protected function route() { $this->dispatch('route'); $params = $this->getRequestData(); //backward compatibility for restler 2 and below if (!Defaults::$smartParameterParsing) { $params = $params + array(Defaults::$fullRequestDataName => $params); } $this->apiMethodInfo = $o = Routes::find($this->url, $this->requestMethod, $this->requestedApiVersion, $params); //set defaults based on api method comments if (isset($o->metadata)) { foreach (Defaults::$fromComments as $key => $defaultsKey) { if (array_key_exists($key, $o->metadata)) { $value = $o->metadata[$key]; Defaults::setProperty($defaultsKey, $value); } } } if (!isset($o->className)) { throw new RestException(404); } if (isset($this->apiVersionMap[$o->className])) { Scope::$classAliases[Util::getShortName($o->className)] = $this->apiVersionMap[$o->className][$this->requestedApiVersion]; } foreach ($this->authClasses as $auth) { if (isset($this->apiVersionMap[$auth])) { Scope::$classAliases[$auth] = $this->apiVersionMap[$auth][$this->requestedApiVersion]; } elseif (isset($this->apiVersionMap[Scope::$classAliases[$auth]])) { Scope::$classAliases[$auth] = $this->apiVersionMap[Scope::$classAliases[$auth]][$this->requestedApiVersion]; } } }
/** * Main function for processing the api request * and return the response * * @throws Exception when the api service class is missing * @throws RestException to send error response */ public function handle() { try { $this->init(); foreach ($this->filterClasses as $filterClass) { /** * @var iFilter */ $filterObj = new $filterClass(); $filterObj->restler = $this; if (!$filterObj instanceof iFilter) { throw new RestException(500, 'Filter Class ' . 'should implement iFilter'); } else { $ok = $filterObj->__isAllowed(); if (is_null($ok) && $filterObj instanceof iUseAuthentication) { //handle at authentication stage $this->filterObjects[] = $filterObj; continue; } throw new RestException(403); //Forbidden } } Util::setProperties(get_class($this->requestFormat), null, $this->requestFormat); $this->requestData = $this->getRequestData(); //parse defaults foreach ($_GET as $key => $value) { if (isset(Defaults::$aliases[$key])) { $_GET[Defaults::$aliases[$key]] = $value; unset($_GET[$key]); $key = Defaults::$aliases[$key]; } if (in_array($key, Defaults::$overridables)) { Defaults::setProperty($key, $value); } } $this->apiMethodInfo = $o = $this->mapUrlToMethod(); if (isset($o->metadata)) { foreach (Defaults::$fromComments as $key => $defaultsKey) { if (array_key_exists($key, $o->metadata)) { $value = $o->metadata[$key]; Defaults::setProperty($defaultsKey, $value); } } } $result = null; if (!isset($o->className)) { $this->handleError(404); } else { try { $accessLevel = max(Defaults::$apiAccessLevel, $o->accessLevel); if ($accessLevel || count($this->filterObjects)) { if (!count($this->authClasses)) { throw new RestException(401); } foreach ($this->authClasses as $authClass) { $authObj = Util::setProperties($authClass, $o->metadata); if (!method_exists($authObj, Defaults::$authenticationMethod)) { throw new RestException(500, 'Authentication Class ' . 'should implement iAuthenticate'); } elseif (!$authObj->{Defaults::$authenticationMethod}()) { throw new RestException(401); } } $this->authenticated = true; } } catch (RestException $e) { if ($accessLevel > 1) { //when it is not a hybrid api $this->handleError($e->getCode(), $e->getMessage()); } else { $this->authenticated = false; } } try { foreach ($this->filterObjects as $filterObj) { Util::setProperties(get_class($filterObj), $o->metadata, $filterObj); } $preProcess = '_' . $this->requestFormat->getExtension() . '_' . $o->methodName; $this->apiMethod = $o->methodName; $object = $this->apiClassInstance = null; // TODO:check if the api version requested is allowed by class if (Defaults::$autoValidationEnabled) { foreach ($o->metadata['param'] as $index => $param) { $info =& $param[CommentParser::$embeddedDataName]; if (!isset($info['validate']) || $info['validate'] != false) { if (isset($info['method'])) { if (!isset($object)) { $object = $this->apiClassInstance = Util::setProperties($o->className); } $info['apiClassInstance'] = $object; } //convert to instance of ValidationInfo $info = new ValidationInfo($param); $valid = Validator::validate($o->arguments[$index], $info); $o->arguments[$index] = $valid; } } } if (!isset($object)) { $object = $this->apiClassInstance = Util::setProperties($o->className); } if (method_exists($o->className, $preProcess)) { call_user_func_array(array($object, $preProcess), $o->arguments); } switch ($accessLevel) { case 3: //protected method $reflectionMethod = new ReflectionMethod($object, $o->methodName); $reflectionMethod->setAccessible(true); $result = $reflectionMethod->invokeArgs($object, $o->arguments); break; default: $result = call_user_func_array(array($object, $o->methodName), $o->arguments); } } catch (RestException $e) { $this->handleError($e->getCode(), $e->getMessage()); } } $this->sendData($result); } catch (RestException $e) { $this->handleError($e->getCode(), $e->getMessage()); } catch (\Exception $e) { $this->log[] = $e->getMessage(); if ($this->productionMode) { $this->handleError(500); } else { $this->handleError(500, $e->getMessage()); } } }
/** * Find the api method to execute for the requested Url */ protected function route() { $this->dispatch('route'); $params = $this->getRequestData(); $currentUrl = 'v' . $this->requestedApiVersion; if (!empty($this->url)) { $currentUrl .= '/' . $this->url; } $this->apiMethodInfo = $o = Routes::find($currentUrl, $this->requestMethod, $params); //set defaults based on api method comments if (isset($o->metadata)) { foreach (Defaults::$fromComments as $key => $defaultsKey) { if (array_key_exists($key, $o->metadata)) { $value = $o->metadata[$key]; Defaults::setProperty($defaultsKey, $value); } } } if (!isset($o->className)) { throw new RestException(404); } }