Http (#3926)
[openemr.git] / apis / dispatch.php
blob5fadd94cf0431b724d9261a6491711fc07e5e0a5
1 <?php
3 /**
4 * Rest Dispatch
6 * @package OpenEMR
7 * @link http://www.open-emr.org
8 * @author Matthew Vita <matthewvita48@gmail.com>
9 * @author Jerry Padgett <sjpadgett@gmail.com>
10 * @author Brady Miller <brady.g.miller@gmail.com>
11 * @copyright Copyright (c) 2018 Matthew Vita <matthewvita48@gmail.com>
12 * @copyright Copyright (c) 2018 Jerry Padgett <sjpadgett@gmail.com>
13 * @copyright Copyright (c) 2019 Brady Miller <brady.g.miller@gmail.com>
14 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
17 require_once("./../_rest_config.php");
19 $gbl = RestConfig::GetInstance();
20 $base_path = $gbl::$ROOT_URL;
21 $routes = array();
22 $resource = '';
24 // Parse needed information from Redirect or REQUEST_URI
25 if (!empty($_REQUEST['_REWRITE_COMMAND'])) {
26 $resource = "/" . $_REQUEST['_REWRITE_COMMAND'];
27 } elseif (!empty($_SERVER['REDIRECT_QUERY_STRING'])) {
28 $resource = str_replace('_REWRITE_COMMAND=', '/', $_SERVER['REDIRECT_QUERY_STRING']);
29 } else {
30 if (!empty($_SERVER['REQUEST_URI'])) {
31 if (strpos($_SERVER['REQUEST_URI'], '?') > 0) {
32 $resource = strstr($_SERVER['REQUEST_URI'], '?', true);
33 } else {
34 $resource = str_replace("$base_path", '', $_SERVER['REQUEST_URI']);
38 $GLOBALS['resource'] = $resource;
40 if (!empty($_SERVER['HTTP_APICSRFTOKEN'])) {
41 // Calling api from within the same session (ie. isLocalApi) since a apicsrftoken header was passed
42 $isLocalApi = true;
43 $gbl::setLocalCall();
44 $ignoreAuth = false;
45 } elseif ($gbl::is_authentication($resource)) {
46 // Get a site id from initial login authentication.
47 $isLocalApi = false;
48 $data = (array) $gbl::getPostData((file_get_contents("php://input")));
49 $site = empty($data['scope']) ? "default" : $data['scope'];
50 $_GET['site'] = $site;
51 $ignoreAuth = true;
52 } else {
53 $isLocalApi = false;
54 $token = $gbl::get_bearer_token();
55 $token_decoded = base64_decode($token, true);
56 if (!empty($token_decoded)) {
57 $tokenParts = json_decode($token_decoded, true);
58 } else {
59 $tokenParts = '';
61 // token needs to have be an array and have something, api needs to be 4 characters, site id needs to be something.
62 if (
63 (is_array($tokenParts)) &&
64 (!empty($tokenParts)) &&
65 (!empty($tokenParts['token'])) &&
66 (!empty($tokenParts['api'])) &&
67 (strlen($tokenParts['api']) == 4) &&
68 (!empty($tokenParts['site_id']))
69 ) {
70 $gbl::verify_api_request($resource, $tokenParts['api']);
71 $_SERVER["HTTP_X_API_TOKEN"] = $tokenParts['token']; // set token to further the adventure.
72 $_GET['site'] = $tokenParts['site_id']; // site id
73 $ignoreAuth = true;
74 } else {
75 // something not right, so exit
76 http_response_code(401);
77 exit();
80 $GLOBALS['is_local_api'] = $isLocalApi;
82 // Set $sessionAllowWrite to true here for following reasons:
83 // 1. !$isLocalApi - in this case setting sessions far downstream and no benefit to set to false since single process
84 // 2. $isLocalApi - in this case, basically setting this to true downstream after some session sets via session_write_close() call
85 $sessionAllowWrite = true;
86 require_once("./../interface/globals.php");
88 use OpenEMR\Common\Csrf\CsrfUtils;
89 use OpenEMR\Common\Http\HttpRestRouteHandler;
90 use OpenEMR\Events\RestApiExtend\RestApiCreateEvent;
93 //Extend API using RestApiCreateEvent
94 $restApiCreateEvent = new RestApiCreateEvent($gbl::$ROUTE_MAP, $gbl::$FHIR_ROUTE_MAP, $gbl::$PORTAL_ROUTE_MAP, $gbl::$PORTAL_FHIR_ROUTE_MAP);
95 $restApiCreateEvent = $GLOBALS["kernel"]->getEventDispatcher()->dispatch(RestApiCreateEvent::EVENT_HANDLE, $restApiCreateEvent, 10);
96 $gbl::$ROUTE_MAP = $restApiCreateEvent->getRouteMap();
97 $gbl::$FHIR_ROUTE_MAP = $restApiCreateEvent->getFHIRRouteMap();
98 $gbl::$PORTAL_ROUTE_MAP = $restApiCreateEvent->getPortalRouteMap();
99 $gbl::$PORTAL_FHIR_ROUTE_MAP = $restApiCreateEvent->getPortalFHIRRouteMap();
101 if ($isLocalApi) {
102 // need to check for csrf match when using api locally
103 $csrfFail = false;
105 if (empty($_SERVER['HTTP_APICSRFTOKEN'])) {
106 error_log("OpenEMR Error: internal api failed because csrf token not received");
107 $csrfFail = true;
110 if ((!$csrfFail) && (!CsrfUtils::verifyCsrfToken($_SERVER['HTTP_APICSRFTOKEN'], 'api'))) {
111 error_log("OpenEMR Error: internal api failed because csrf token did not match");
112 $csrfFail = true;
115 if ($csrfFail) {
116 http_response_code(401);
117 exit();
121 // api flag must be four chars
122 // Pass only routes for current api.
123 // Also check to ensure route is turned on in globals
124 if ($gbl::is_fhir_request($resource)) {
125 if (!$GLOBALS['rest_fhir_api'] && !$isLocalApi) {
126 // if the external fhir api is turned off and this is not a local api call, then exit
127 http_response_code(501);
128 exit();
130 $_SESSION['api'] = 'fhir';
131 $routes = $gbl::$FHIR_ROUTE_MAP;
132 } elseif ($gbl::is_portal_request($resource)) {
133 if (!$GLOBALS['rest_portal_api'] && !$isLocalApi) {
134 // if the external portal api is turned off and this is not a local api call, then exit
135 http_response_code(501);
136 exit();
138 $_SESSION['api'] = 'port';
139 $routes = $gbl::$PORTAL_ROUTE_MAP;
140 } elseif ($gbl::is_portal_fhir_request($resource)) {
141 if (!$GLOBALS['rest_portal_fhir_api'] && !$isLocalApi) {
142 // if the external portal fhir api is turned off and this is not a local api call, then exit
143 http_response_code(501);
144 exit();
146 $_SESSION['api'] = 'pofh';
147 $routes = $gbl::$PORTAL_FHIR_ROUTE_MAP;
148 } elseif ($gbl::is_api_request($resource)) {
149 if (!$GLOBALS['rest_api'] && !$isLocalApi) {
150 // if the external api is turned off and this is not a local api call, then exit
151 http_response_code(501);
152 exit();
154 $_SESSION['api'] = 'oemr';
155 $routes = $gbl::$ROUTE_MAP;
156 } else {
157 // somebody is up to no good
158 http_response_code(501);
159 exit();
162 if ($isLocalApi) {
163 // Ensure that a local process does not hold up other processes
164 // Note can not do this for !$isLocalApi since need to be able to set
165 // session variables and it won't help performance anyways.
166 session_write_close();
169 if (!$isLocalApi) {
170 $gbl::authentication_check($resource);
172 // dispatch $routes called by ref.
173 $hasRoute = HttpRestRouteHandler::dispatch($routes, $resource, $_SERVER["REQUEST_METHOD"]);
174 // Tear down session for security.
175 if (!$isLocalApi) {
176 $gbl::destroySession();
178 // prevent 200 if route doesn't exist
179 if (!$hasRoute) {
180 http_response_code(404);