File modules/cms/output/APIOutput.class.php

Last commit: Mon Jun 13 22:00:39 2022 +0200	Jan Dankert	Fix: Show the error description in the UI notice.
1 <?php 2 3 namespace cms\output; 4 5 use BadMethodCallException; 6 use cms\action\RequestParams; 7 use cms\base\Startup; 8 use Exception; 9 use util\exception\ClientException; 10 use util\Session; 11 12 /** 13 * Entrypoint for all API requests. 14 */ 15 abstract class APIOutput extends BaseOutput 16 { 17 /** 18 * Converting an exception to an array. 19 * 20 * This will contain all exceptions out of the exception chain. 21 * 22 * @param $e Exception 23 */ 24 private static function exceptionToArray($e) 25 { 26 $data = array( 27 'error' => get_class($e), 28 'description'=> $e->getMessage(), 29 'code' => $e->getCode(), 30 31 'trace'=>array_merge( array( array( 32 'file' => $e->getFile(), 33 'line' => $e->getLine(), 34 'function' => '', 35 'class' => '', 36 )), self::removeArgsFromTrace($e->getTrace())) 37 ); 38 39 // the cause of the exception is another exception. 40 if ( $e->getPrevious() ) 41 $data['cause'] = self::exceptionToArray($e->getPrevious() ); 42 43 return $data; 44 } 45 46 /** 47 * This method is executed before the dispatcher is called. 48 * Subclasses may override this to prepare the response. 49 * @param $request RequestParams 50 * @return void 51 */ 52 protected function beforeAction( $request ) 53 { 54 if ( ! $request->action ) 55 throw new ClientException('no action set'); 56 if ( ! $request->method ) 57 throw new ClientException('no subaction set'); 58 } 59 60 61 /** 62 * Removing the call argument from the trace. 63 * 64 * This is because of security reasons. The arguments could be an information leak. 65 * 66 * @param $trace array 67 * @return array 68 */ 69 private static function removeArgsFromTrace($trace) 70 { 71 foreach( $trace as &$t ) 72 { 73 unset($t['args']); 74 } 75 76 return $trace; 77 } 78 79 protected function outputData($request, $data) 80 { 81 $data += [ 82 'session' => [ 83 'name' => session_name(), 84 'id' => session_id(), 85 'token' => Session::token() 86 ], 87 'version' => Startup::VERSION, 88 'api' => Startup::API_LEVEL, 89 ]; 90 91 $output = $this->renderOutput( $data ); 92 93 // HTTP Spec: 94 // "Applications SHOULD use this field to indicate the transfer-length of the 95 // message-body, unless this is prohibited by the rules in section 4.4." 96 // 97 // And the overhead of 'Transfer-Encoding: chunked' is eliminated... 98 header('Content-Length: ' . strlen($output)); 99 echo $output; 100 } 101 102 abstract protected function renderOutput( $data ); 103 104 /** 105 * @param string $text 106 * @param Exception $cause 107 */ 108 protected function setError($text, $cause) 109 { 110 $data = [ 111 'message' => $text, 112 'notices' => [ 113 [ 114 'status'=> 'error', 115 'text' => $text, 116 'log' => (!defined('DEVELOPMENT') || DEVELOPMENT) ? $cause->getMessage() : '', 117 ] 118 ], 119 'errors' => [], 120 ]; 121 122 // Traces only in DEVELOPMENT mode 123 // for security reasons, because traces may contain sensitive information. 124 if (!defined('DEVELOPMENT') || DEVELOPMENT) 125 $data['cause'] = $this->exceptionToArray($cause); 126 127 $this->outputData(null,$data); 128 } 129 130 }
Download modules/cms/output/APIOutput.class.php
History Mon, 13 Jun 2022 22:00:39 +0200 Jan Dankert Fix: Show the error description in the UI notice. Sat, 19 Mar 2022 01:29:19 +0100 dankert Fix: PreviewOutput should inherit from UIOutput. Fri, 11 Mar 2022 12:13:10 +0100 dankert Fix: Show notice on internal server error. Wed, 2 Feb 2022 01:12:42 +0100 dankert Better support for API requests. Sun, 30 Jan 2022 23:38:42 +0100 dankert Refactoring: Only 1 http-endpoint for both the UI and the API. Path "/api" is not available any more, all API data is served under "/".