Skip to content
This repository was archived by the owner on Sep 10, 2021. It is now read-only.

Commit 19afa97

Browse files
committed
ENH: Refs #0963. Added RESTful Web APIs. Added RESTful api documents sample using Swagger
1 parent 2d9e48f commit 19afa97

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+11448
-1553
lines changed

core/ApiController.php

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
<?php
2+
/*=========================================================================
3+
MIDAS Server
4+
Copyright (c) Kitware SAS. 26 rue Louis Guérin. 69100 Villeurbanne, FRANCE
5+
All rights reserved.
6+
More information http://www.kitware.com
7+
8+
Licensed under the Apache License, Version 2.0 (the "License");
9+
you may not use this file except in compliance with the License.
10+
You may obtain a copy of the License at
11+
12+
http://www.apache.org/licenses/LICENSE-2.0.txt
13+
14+
Unless required by applicable law or agreed to in writing, software
15+
distributed under the License is distributed on an "AS IS" BASIS,
16+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17+
See the License for the specific language governing permissions and
18+
limitations under the License.
19+
=========================================================================*/
20+
21+
/** Web Api Controller */
22+
class ApiController extends REST_Controller
23+
{
24+
25+
private $httpSuccessCode = array(
26+
'index' => 200, // 200 OK
27+
'get' => 200,
28+
'post' => 201, // 201 Created
29+
'put' => 200,
30+
'delete' => 200
31+
);
32+
33+
/** init api actions*/
34+
public function init()
35+
{
36+
$this->disableLayout();
37+
$this->disableView();
38+
$this->_response->setBody(null);
39+
$this->_response->setHttpResponseCode(200); // 200 OK
40+
}
41+
42+
/** Return the user dao */
43+
protected function _getUser($args)
44+
{
45+
$authComponent = MidasLoader::loadComponent('Authentication', 'api');
46+
return $authComponent->getUser($args, $this->userSession->Dao);
47+
}
48+
49+
/** Convert Midas internal error code to standard HTTP status code */
50+
protected function _exceptionHandler(Exception $e)
51+
{
52+
$errorInfo['code'] = $e->getCode();
53+
$errorInfo['msg'] = $e->getMessage();
54+
switch ($errorInfo['code'])
55+
{
56+
case MIDAS_INVALID_PARAMETER:
57+
case MIDAS_INVALID_POLICY:
58+
case MIDAS_INTERNAL_ERROR:
59+
case MIDAS_HTTP_ERROR:
60+
case MIDAS_UPLOAD_FAILED:
61+
case MIDAS_UPLOAD_TOKEN_GENERATION_FAILED:
62+
case MIDAS_SOURCE_OPEN_FAILED:
63+
case MIDAS_OUTPUT_OPEN_FAILED:
64+
$httpCode = 400; // 400 Bad Request
65+
break;
66+
case MIDAS_INVALID_TOKEN:
67+
case MIDAS_INVALID_UPLOAD_TOKEN:
68+
$httpCode = 401; // 401 Unauthorized
69+
break;
70+
default:
71+
$httpCode = 400; // 400 Bad Request
72+
}
73+
return array($errorInfo, $httpCode);
74+
}
75+
76+
/**
77+
* Generic wapper function called by restful actions.
78+
* With the given arguments, it calls the related function in the corresponding
79+
* ApiComponent and then fill http status code and results in the response.
80+
*
81+
* @param array $args Parameters got from http request.
82+
* @param string $restAction Restful actions: get, index, post, put or delete.
83+
* @param array $apiFunctions An array of
84+
* method name in restful action => function name in correspoding ApiComponent
85+
* This array must have 'default' in its keys.
86+
* @param string $moduleName Which module to get the ApiComponent
87+
*
88+
* Example:
89+
* _generacAction(array('id' => 2), 'get', $apiFunctionArray) is called
90+
* and $apiFunctionArray is
91+
* $apiFunctions = array(
92+
* 'default' => 'itemMove',
93+
* 'move' => 'itemMove',
94+
* 'duplicate' => 'itemDuplicate'
95+
* );
96+
*
97+
* for 'curl -v {base_path}/rest/item/move/2' command, Midas will call
98+
* 'itemMove' in ApiComponent (in core module) to do the api work;
99+
* for given url: {base_path}/rest/item/2, Midas will call
100+
* 'itemMove' in ApiComponent (in core module) to do the api;
101+
* for given url: {base_path}/rest/item/duplicate/2, Midas will call
102+
* 'itemDuplicate' in ApiComponent (in core module) to do the api;
103+
*/
104+
105+
protected function _genericAction($args, $restAction, $apiFunctions, $moduleName = null)
106+
{
107+
$ApiComponent = MidasLoader::loadComponent('Api', $moduleName);
108+
$httpCode = $this->httpSuccessCode[strtolower($restAction)];
109+
$calledFunction = $apiFunctions['default'];
110+
$apiResults = array();
111+
try
112+
{
113+
$userDao = $this->_getUser($args);
114+
if(isset($args['method']))
115+
{
116+
$method = strtolower($args['method']);
117+
if(array_key_exists($method, $apiFunctions))
118+
{
119+
$calledFunction = $apiFunctions[$method];
120+
}
121+
else
122+
{
123+
throw new Exception('Server error. Operation ' . $args['method'] . ' is not supported.', -100);
124+
}
125+
}
126+
$resulstArray = $ApiComponent->$calledFunction($args, $userDao);
127+
if (isset($resulstArray))
128+
{
129+
$apiResults['data'] = $resulstArray;
130+
}
131+
else // if the api function doesn't provide an return value
132+
{
133+
$apiResults['msg'] = "succeed!"; // there is no exception if code reaches here
134+
}
135+
}
136+
catch (Exception $e)
137+
{
138+
list($apiResults['error'], $httpCode) = $this->_exceptionHandler($e);
139+
}
140+
$this->_response->setHttpResponseCode($httpCode);
141+
// only the data assigned to '$this->view->apiresults' will be serilized
142+
// in requested format (json, xml, etc) and filled in response body
143+
$this->view->apiresults = $apiResults;
144+
}
145+
146+
/**
147+
* The index action handles index/list requests; it should respond with a
148+
* list of the requested resources.
149+
*/
150+
public function indexAction()
151+
{
152+
$this->_response->setHttpResponseCode(405); // 405 Method Not Allowed
153+
}
154+
155+
/**
156+
* The head action handles HEAD requests; it should respond with an
157+
* identical response to the one that would correspond to a GET request,
158+
* but without the response body.
159+
*/
160+
public function headAction()
161+
{
162+
$this->_response->setHttpResponseCode(405); // 405 Method Not Allowed
163+
}
164+
165+
/**
166+
* The get action handles GET requests and receives an 'id' parameter; it
167+
* should respond with the server resource state of the resource identified
168+
* by the 'id' value.
169+
*/
170+
public function getAction()
171+
{
172+
$this->_response->setHttpResponseCode(405); // 405 Method Not Allowed
173+
}
174+
175+
/**
176+
* The post action handles POST requests; it should accept and digest a
177+
* POSTed resource representation and persist the resource state.
178+
*/
179+
public function postAction()
180+
{
181+
$this->_response->setHttpResponseCode(405); // 405 Method Not Allowed
182+
}
183+
184+
/**
185+
* The put action handles PUT requests and receives an 'id' parameter; it
186+
* should update the server resource state of the resource identified by
187+
* the 'id' value.
188+
*/
189+
public function putAction()
190+
{
191+
$this->_response->setHttpResponseCode(405); // 405 Method Not Allowed
192+
}
193+
194+
/**
195+
* The delete action handles DELETE requests and receives an 'id'
196+
* parameter; it should update the server resource state of the resource
197+
* identified by the 'id' value.
198+
*/
199+
public function deleteAction()
200+
{
201+
$this->_response->setHttpResponseCode(405); // 405 Method Not Allowed
202+
}
203+
204+
/**
205+
* The options action handles OPTIONS requests; it should respond with
206+
* the HTTP methods that the server supports for specified URL.
207+
*/
208+
public function optionsAction()
209+
{
210+
$this->_response->setHeader('Allow', 'OPTIONS');
211+
}
212+
213+
} //end class
214+
?>

core/Bootstrap.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,18 +197,37 @@ protected function _initRouter()
197197
$modules = new Zend_Config_Ini(APPLICATION_CONFIG, 'module');
198198
// routes modules
199199
$listeModule = array();
200+
$apiModules = array();
200201
foreach($modules as $key => $module)
201202
{
202203
if($module == 1 && file_exists(BASE_PATH.'/modules/'.$key) && file_exists(BASE_PATH . "/modules/".$key."/AppController.php"))
203204
{
204205
$listeModule[] = $key;
206+
// get WebApi controller directories and WebApi module names for enabled modules
207+
if(file_exists(BASE_PATH . "/modules/".$key."/controllers/api"))
208+
{
209+
$frontController->addControllerDirectory(BASE_PATH . "/modules/".$key."/controllers/api", "api".$key);
210+
$apiModules[] = $key;
211+
}
205212
}
206213
elseif($module == 1 && file_exists(BASE_PATH.'/privateModules/'.$key) && file_exists(BASE_PATH . "/privateModules/".$key."/AppController.php"))
207214
{
208215
$listeModule[] = $key;
216+
// get WebApi controller directories and WebApi module names for enabled modules
217+
if(file_exists(BASE_PATH . "/privateModules/".$key."/controllers/api"))
218+
{
219+
$frontController->addControllerDirectory(BASE_PATH . "/privateModules/".$key."/controllers/api", "api".$key);
220+
$apiModules[] = $key;
221+
}
209222
}
210223
}
211224

225+
// get WebApi controller directory for core Apis
226+
require_once BASE_PATH . "/core/ApiController.php";
227+
$frontController->addControllerDirectory(BASE_PATH . '/core/controllers/api', 'rest');
228+
// add restful route for WebApis
229+
$restRoute = new Zend_Rest_Route($frontController, array(), array('rest'));
230+
$router->addRoute('api-core', $restRoute);
212231
// loading modules elements
213232
foreach($listeModule as $m)
214233
{
@@ -286,7 +305,26 @@ protected function _initRouter()
286305
}
287306
}
288307
Zend_Registry::set('modulesEnable', $listeModule);
308+
Zend_Registry::set('modulesHaveApi', $apiModules);
289309
return $router;
290310
}
311+
312+
/** register plugins and helpers for REST_Controller*/
313+
protected function _initREST()
314+
{
315+
$frontController = Zend_Controller_Front::getInstance();
316+
317+
// register the RestHandler plugin
318+
$frontController->registerPlugin(new REST_Controller_Plugin_RestHandler($frontController));
319+
320+
// add REST contextSwitch helper
321+
$contextSwitch = new REST_Controller_Action_Helper_ContextSwitch();
322+
Zend_Controller_Action_HelperBroker::addHelper($contextSwitch);
323+
324+
// add restContexts helper
325+
$restContexts = new REST_Controller_Action_Helper_RestContexts();
326+
Zend_Controller_Action_HelperBroker::addHelper($restContexts);
327+
}
328+
291329
}
292330

core/apidocs/api-docs.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"apiVersion":"0.2",
3+
"swaggerVersion":"1.1",
4+
"basePath":"http://localhost/midas/core/apidocs",
5+
"apis":[
6+
{
7+
"path":"/models/item",
8+
"description":"Operations about item"
9+
},
10+
{
11+
"path":"/models/sizequota_user",
12+
"description":"Operations about user's sizequote"
13+
}
14+
]
15+
}

0 commit comments

Comments
 (0)