diff --git a/lizmap/modules/lizmap/lib/Request/OGCRequest.php b/lizmap/modules/lizmap/lib/Request/OGCRequest.php index 5093b92b3d..ee32f39dae 100644 --- a/lizmap/modules/lizmap/lib/Request/OGCRequest.php +++ b/lizmap/modules/lizmap/lib/Request/OGCRequest.php @@ -185,6 +185,78 @@ protected function constructUrl() return Proxy::constructUrl($this->parameters(), $this->services, $url); } + /** + * Generate a string to identify the target of the HTTP request. + * + * @param array $parameters The list of HTTP parameters in the query + * @param int $code The HTTP code of the request + * + * @return string The string to identify the HTTP request, with main OGC parameters first such as MAP, SERVICE... + */ + private function formatHttpErrorString($parameters, $code) + { + // Clone parameters array to perform unset without modify it + $params = array_merge(array(), $parameters); + + // Ordered list of params to fetch first + $mainParamsToLog = array('map', 'repository', 'project', 'service', 'request'); + + $output = array(); + foreach ($mainParamsToLog as $paramName) { + if (array_key_exists($paramName, $params)) { + $output[] = '"'.strtoupper($paramName).'" = '."'".$params[$paramName]."'"; + unset($params[$paramName]); + } + } + + // First implode with main parameters + $message = implode(' & ', $output); + + if ($params) { + // Ideally, we want two lines, one with main parameters, the second one with secondary parameters + // It does not work in jLog + // $message .= '\n'; + $message .= ' & '; + } + + // For remaining parameters in the array, which are not in the main list + $output = array(); + foreach ($params as $key => $value) { + $output[] = '"'.strtoupper($key).'" = '."'".$value."'"; + } + + $message .= implode(' & ', $output); + + return 'HTTP code '.$code.' on '.$message; + } + + /** + * Log if the HTTP code is a 4XX or 5XX error code. + * + * @param int $code The HTTP code of the request + */ + protected function logRequestIfError($code) + { + if ($code < 400) { + return; + } + + $message = 'The HTTP OGC request to QGIS Server ended with an error.'; + + // The master error with MAP parameter + // This user must have an access to QGIS Server logs + $params = $this->parameters(); + \jLog::log($message.' Check logs on QGIS Server. '.$this->formatHttpErrorString($params, $code), 'error'); + + // The admin error without the MAP parameter + // but replaced by REPOSITORY and PROJECT parameters + // This user might not have an access to QGIS Server logs + unset($params['map']); + $params['repository'] = $this->project->getRepository()->getKey(); + $params['project'] = $this->project->getKey(); + \jLog::log($message.' '.$this->formatHttpErrorString($params, $code), 'lizmapadmin'); + } + /** * Request QGIS Server. * @@ -236,11 +308,15 @@ protected function request($post = false, $stream = false) if ($stream) { $response = \Lizmap\Request\Proxy::getRemoteDataAsStream($querystring, $options); + $this->logRequestIfError($response->getCode()); + return new OGCResponse($response->getCode(), $response->getMime(), $response->getBodyAsStream()); } list($data, $mime, $code) = \Lizmap\Request\Proxy::getRemoteData($querystring, $options); + $this->logRequestIfError($code); + return new OGCResponse($code, $mime, $data); } diff --git a/lizmap/modules/lizmap/lib/Request/Proxy.php b/lizmap/modules/lizmap/lib/Request/Proxy.php index 5a912b72f5..de3d433e1f 100644 --- a/lizmap/modules/lizmap/lib/Request/Proxy.php +++ b/lizmap/modules/lizmap/lib/Request/Proxy.php @@ -489,14 +489,14 @@ protected static function fileProxy($url, $options) * @param int $httpCode The HTTP code of the request * @param string $url The URL of the request, for logging */ - public static function logRequestIfError($httpCode, $url) + protected static function logRequestIfError($httpCode, $url) { - $httpCodeClass = substr($httpCode, 0, 1); - // Change to str_starts_with when PHP 8.1 will be minimum version for all maintained version - if ($httpCodeClass == '4' || $httpCodeClass == '5') { - \jLog::log('An HTTP request ended with an error, please check the main error log. Code '.$httpCode, 'lizmapadmin'); - \jLog::log('The HTTP request below ended with an error. Code '.$httpCode.' → '.$url, 'error'); + if ($httpCode < 400) { + return; } + + \jLog::log('An HTTP request ended with an error, please check the main error log. HTTP code '.$httpCode, 'lizmapadmin'); + \jLog::log('The HTTP request ended with an error. HTTP code '.$httpCode.' → '.$url, 'error'); } /** diff --git a/lizmap/modules/view/locales/en_US/dictionnary.UTF-8.properties b/lizmap/modules/view/locales/en_US/dictionnary.UTF-8.properties index b31e342c28..c6e52b4a84 100644 --- a/lizmap/modules/view/locales/en_US/dictionnary.UTF-8.properties +++ b/lizmap/modules/view/locales/en_US/dictionnary.UTF-8.properties @@ -1,6 +1,6 @@ startup.error=An error occurred while loading this map. Some necessary resources may temporarily be unavailable. Please try again later. startup.error.administrator=Please notify the administrator of this map to connect and visit this map. -startup.error.developer.tools=Maybe you will have a clue by opening your "Developer tools" in your web-browser. It's usually F12. Check "Console" and "Networks". +startup.error.developer.tools=Maybe you will have a clue by opening your "Developer tools" in your web-browser. It's usually F12. Check "Console" and "Networks".\n\nVisit the administration panel and check in the log page if an HTTP request ended with an error related to this project. startup.user_defined_js=This map contains some users additional JavaScript scripts. This can be the cause of this message, try disabling them. startup.goToProject=Home startup.goToRepositoryAdmin=Maps management page