slug = $slug; if(isset($description)) $this->description = $description; $this->route = array(); return $this; } function route($slug = null,$description = null,$method = null,$callback){ $route = new ApiRoute($slug,$description,$method,$callback); $this->route[$route->slug][$method] = $route; } function register(){ Plugin::addHook('api',function(&$apis){ $apis[$this->slug] = $this; }); } public static function run(){ global $_,$myUser; $response = array(); try{ /*set_error_handler(function( $errno , $errstr , $errfile , $errline){ throw new Exception("Error ".$errno." Processing Request ".$errfile.$errstr, 500); }); register_shutdown_function(function( $errno , $errstr , $errfile , $errline){ $error = error_get_last(); throw new Exception("Error ".E_CORE_ERROR." Processing Request ".$error['file'], 500); });*/ $command = explode('/',$_['command']); if(count($command)<1) throw new Exception("Unspecified API"); $headers = apache_request_headers(); //basic auth if(isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW'])){ $user = User::check($_SERVER['PHP_AUTH_USER'],$_SERVER['PHP_AUTH_PW']); if(!$user) throw new Exception('Le compte spécifié est inexistant'); $myUser = $user; } $request = array( 'version' =>array_shift($command), 'module' =>array_shift($command), 'route' =>array_shift($command), 'body' =>file_get_contents("php://input"), 'method' => strtoupper($_SERVER['REQUEST_METHOD']), 'parameters' => $_, 'pathes' => array_filter($command) ); $code = 200; $headers = array( 'Content-Type: application/json' ); $apis = array(); Plugin::callHook('api',array(&$apis)); //format de l'url : /api/v{version}/ if(!isset($request['version']) || !is_numeric(substr($request['version'],1)) || substr($request['version'], 0,1)!='v') throw new Exception("Api version is missing or invalid, specify ".ROOT_URL."/api/{version} for valid requests", 404); if($request['module'] == 'schema'){ foreach ($apis as $api) { $routes= array(); foreach($api->route as $route){ foreach($route as $method=>$infos){ if(!isset($routes[$infos->slug])) $routes[$infos->slug] = array() ; $routes[$infos->slug][] = $infos->method.' '.$api->slug .'/'.$infos->pattern .': '. $infos->description ; } } $response[] = array( $api->slug => $api->description,'routes'=> $routes); } }else{ if(!isset($apis[$request['module']])) throw new Exception("Api '".$request['module']."' is missing, see ".ROOT_URL."/api/schema for available calls", 404); $api = $apis[$request['module']]; if(!isset($api->route[$request['route']])) throw new Exception("Route '".$api->slug.'/'.$request['route']."' is missing, see ".ROOT_URL."/api/schema?pretty for available calls", 404); $route = $api->route[$request['route']]; if(!isset($route[$request['method']])) throw new Exception("Method ".$request['method']." '".$api->slug.'/'.$route->slug."' is not allowed", 405); $method = $route[$request['method']]; $callback = $method->callback; $callback($request,$response); if(isset($response['code'])) $code = $response['code']; if(isset($response['headers'])) $headers = array_merge($headers,$response['headers']); unset($response['code']); unset($response['headers']); } }catch(Exception $e){ $response['error'] = $e->getMessage(); $code = $e->getCode(); if(empty($code) || $code==0) $code = 666; } $codes = array( 200 => 'HTTP/1.1 200 Ok', 201 => 'HTTP/1.1 201 Created', 204 => 'HTTP/1.1 204 No Content', 207 => 'HTTP/1.1 207 Multi-Status', 400 => 'HTTP/1.0 400 Bad Request', 401 => 'HTTP/1.0 401 Unauthorized', 403 => 'HTTP/1.1 403 Forbidden', 404 => 'HTTP/1.1 404 Not Found', 404 => 'HTTP/1.1 405 Method Not Allowed', 406 => 'HTTP/1.1 406 Not acceptable', 409 => 'HTTP/1.1 409 Conflict', 415 => 'HTTP/1.1 415 Unsupported Media Type', 423 => 'HTTP/1.1 423 Locked', 500 => 'HTTP/1.1 500 Internal Server Error', 501 => 'HTTP/1.1 501 Not implemented', 666 => 'HTTP/1.1 666 Welcome to Hell mate!', ); if (ob_get_length()) ob_end_clean(); header(isset($codes[$code]) ? $codes[$code] : $codes[666]); foreach ($headers as $header) { header($header); } if(isset($_['pretty'])){ echo json_encode($response,JSON_PRETTY_PRINT); }else{ echo json_encode($response); } exit(); } } class ApiRoute{ public $slug,$description,$callback,$method,$pathes,$parameters,$pattern; function __construct($slug='default',$description='No description',$method='GET',$callback){ $this->pattern = $slug; $infos = explode('?',$slug); if(isset($infos[1])) $this->parameters = $infos[1]; $infos = explode('/',$infos[0]); $this->slug = array_shift($infos); $this->pathes = $infos; $this->description = $description; $this->method = $method; $this->callback = $callback; } } ?>