From 6d4aa258929655d94bc20e4e5fcdb5a3ca352216 Mon Sep 17 00:00:00 2001 From: Jerome Mouneyrac Date: Fri, 14 Oct 2011 12:03:23 +0800 Subject: [PATCH] MDL-29459 REST-XML server validate return values and throw exception if the returned values are bad (missing, not expected, wrong type). Remove from the REST serialize function previous error checking (missing key error, bypassing not expected keys). It now matches other servers that do validate the return values and throw exception --- webservice/rest/locallib.php | 86 +++++++++++++++++++----------------- 1 file changed, 45 insertions(+), 41 deletions(-) diff --git a/webservice/rest/locallib.php b/webservice/rest/locallib.php index afe7c357862..3fe38ea8b9f 100644 --- a/webservice/rest/locallib.php +++ b/webservice/rest/locallib.php @@ -82,56 +82,69 @@ class webservice_rest_server extends webservice_base_server { * @return void */ protected function send_response() { - $this->send_headers(); - if ($this->restformat == 'json') { - try { - $response = external_api::clean_returnvalue($this->function->returns_desc, $this->returns); - } catch (Exception $ex) { - $error = new stdClass; - $error->exception = get_class($ex); - $error->message = $ex->getMessage(); - if (debugging() and isset($ex->debuginfo)) { - $error->debuginfo = $ex->debuginfo; - } - echo json_encode($error); - } - $json = json_encode($response); - echo $json; - } else { - $xml = ''."\n"; - $xml .= ''."\n"; - $xml .= self::xmlize_result($this->returns, $this->function->returns_desc); - $xml .= ''."\n"; - echo $xml; + + //Check that the returned values are valid + try { + $validatedvalues = external_api::clean_returnvalue($this->function->returns_desc, $this->returns); + } catch (Exception $ex) { + $exception = $ex; } + + if (!empty($exception)) { + $response = $this->generate_error($exception); + } else { + //We can now convert the response to the requested REST format + if ($this->restformat == 'json') { + $response = json_encode($validatedvalues); + } else { + $response = ''."\n"; + $response .= ''."\n"; + $response .= self::xmlize_result($this->returns, $this->function->returns_desc); + $response .= ''."\n"; + } + } + + $this->send_headers(); + echo $response; } /** * Send the error information to the WS client * formatted as XML document. + * Note: the exception is never passed as null, + * it only matches the abstract function declaration. * @param exception $ex * @return void */ protected function send_error($ex=null) { $this->send_headers(); + echo $this->generate_error($ex); + } + + /** + * Build the error information matching the REST returned value format (JSON or XML) + * @param exception $ex + * @return string the error in the requested REST format + */ + protected function generate_error($ex) { if ($this->restformat == 'json') { - $error = new stdClass; - $error->exception = get_class($ex); - $error->message = $ex->getMessage(); + $errorobject = new stdClass; + $errorobject->exception = get_class($ex); + $errorobject->message = $ex->getMessage(); if (debugging() and isset($ex->debuginfo)) { - $error->debuginfo = $ex->debuginfo; + $errorobject->debuginfo = $ex->debuginfo; } - echo json_encode($error); + $error = json_encode($errorobject); } else { - $xml = ''."\n"; - $xml .= ''."\n"; - $xml .= ''.htmlentities($ex->getMessage(), ENT_COMPAT, 'UTF-8').''."\n"; + $error = ''."\n"; + $error .= ''."\n"; + $error .= ''.htmlentities($ex->getMessage(), ENT_COMPAT, 'UTF-8').''."\n"; if (debugging() and isset($ex->debuginfo)) { - $xml .= ''.htmlentities($ex->debuginfo, ENT_COMPAT, 'UTF-8').''."\n"; + $error .= ''.htmlentities($ex->debuginfo, ENT_COMPAT, 'UTF-8').''."\n"; } - $xml .= ''."\n"; - echo $xml; + $error .= ''."\n"; } + return $error; } /** @@ -185,15 +198,6 @@ class webservice_rest_server extends webservice_base_server { } else if ($desc instanceof external_single_structure) { $single = ''."\n"; foreach ($desc->keys as $key=>$subdesc) { - if (!array_key_exists($key, $returns)) { - if ($subdesc->required == VALUE_REQUIRED) { - $single .= 'Missing required key "'.$key.'"'; - continue; - } else { - //optional field - continue; - } - } $single .= ''.self::xmlize_result($returns[$key], $subdesc).''."\n"; } $single .= ''."\n";