From 38b56bf23a0b1a4d860d4026083f1a455613b0ea Mon Sep 17 00:00:00 2001 From: LogMANOriginal Date: Sat, 29 Jul 2017 19:16:16 +0200 Subject: [PATCH] [index] Improve error handling (#555) Add additional information to error message: - Name of the bridge - Possible solutions - Error description - Error code - Error message * Output type changed from 'text' to 'html' * Added styles for the error page * Added a button to remotely open a GitHub issue Closes #525 --- index.php | 15 ++++- lib/Exceptions.php | 149 +++++++++++++++++++++++++++++++++++++++++++++ static/style.css | 34 +++++++++++ 3 files changed, 195 insertions(+), 3 deletions(-) diff --git a/index.php b/index.php index 5a24b53..7fc2f8a 100644 --- a/index.php +++ b/index.php @@ -162,8 +162,14 @@ try { unset($params['_noproxy']); // Load cache & data - $bridge->setCache($cache); - $bridge->setDatas($params); + try { + $bridge->setCache($cache); + $bridge->setDatas($params); + } catch(Exception $e){ + header('HTTP/1.1 ' . $e->getCode() . ' ' . Http::getMessageForCode($e->getCode())); + header('Content-Type: text/html'); + die(buildBridgeException($e, $bridge)); + } // Data transformation try { @@ -172,8 +178,11 @@ try { $format->setExtraInfos($bridge->getExtraInfos()); $format->display(); } catch(Exception $e){ - echo "The bridge has crashed. You should report this to the bridges maintainer"; + header('HTTP/1.1 ' . $e->getCode() . ' ' . Http::getMessageForCode($e->getCode())); + header('Content-Type: text/html'); + die(buildTransformException($e, $bridge)); } + die; } } diff --git a/lib/Exceptions.php b/lib/Exceptions.php index 9b90694..ff8ec86 100644 --- a/lib/Exceptions.php +++ b/lib/Exceptions.php @@ -58,3 +58,152 @@ class Http{ ); } } + +/** + * Returns an URL that automatically populates a new issue on GitHub based + * on the information provided + * + * @param $title string Sets the title of the issue + * @param $body string Sets the body of the issue (GitHub markdown applies) + * @param $labels mixed (optional) Specifies labels to add to the issue + * @param $maintainer string (optional) Specifies the maintainer for the issue. + * The maintainer only applies if part of the development team! + * @return string Returns a qualified URL to a new issue with populated conent. + * Returns null if title or body is null or empty + */ +function buildGitHubIssueQuery($title, $body, $labels = null, $maintainer = null){ + if(!isset($title) || !isset($body) || empty($title) || empty($body)) { + return null; + } + + // Add title and body + $uri = 'https://github.com/rss-bridge/rss-bridge/issues/new?title=' + . urlencode($title) + . '&body=' + . urlencode($body); + + // Add labels + if(!is_null($labels) && is_array($labels) && count($labels) > 0) { + if(count($lables) === 1) { + $uri .= '&labels=' . urlencode($labels[0]); + } else { + foreach($labels as $label) { + $uri .= '&labels[]=' . urlencode($label); + } + } + } elseif(!is_null($labels) && is_string($labels)) { + $uri .= '&labels=' . urlencode($labels); + } + + // Add maintainer + if(!empty($maintainer)) { + $uri .= '&assignee=' . urlencode($maintainer); + } + + return $uri; +} + +/** + * Returns the exception message as HTML string + * + * @param $e Exception The exception to show + * @param $bridge object The bridge object + * @return string Returns the exception as HTML string. Returns null if the + * provided parameter are invalid + */ +function buildBridgeException($e, $bridge){ + if(!($e instanceof \Exception) || !($bridge instanceof \BridgeInterface)) { + return null; + } + + $title = $bridge->getName() . ' failed with error ' . $e->getCode(); + + // Build a GitHub compatible message + $body = 'Error message: `' + . $e->getMessage() + . "`\nQuery string: `" + . $_SERVER['QUERY_STRING'] . '`'; + + $link = buildGitHubIssueQuery($title, $body, 'bug report', $bridge->getMaintainer()); + + $header = buildHeader($e, $bridge); + $message = "{$bridge->getName()} was +unable to receive or process the remote website's content!"; + $section = buildSection($e, $bridge, $message, $link); + + return buildPage($title, $header, $section); +} + +/** + * Returns the exception message as HTML string + * + * @param $e Exception The exception to show + * @param $bridge object The bridge object + * @return string Returns the exception as HTML string. Returns null if the + * provided parameter are invalid + */ +function buildTransformException($e, $bridge){ + if(!($e instanceof \Exception) || !($bridge instanceof \BridgeInterface)) { + return null; + } + + $title = $bridge->getName() . ' failed with error ' . $e->getCode(); + + // Build a GitHub compatible message + $body = 'Error message: `' + . $e->getMessage() + . "`\nQuery string: `" + . $_SERVER['QUERY_STRING'] . '`'; + + $link = buildGitHubIssueQuery($title, $body, 'bug report', $bridge->getMaintainer()); + $header = buildHeader($e, $bridge); + $message = "RSS-Bridge was unable to transform the contents returned by +{$bridge->getName()}!"; + $section = buildSection($e, $bridge, $message, $link); + + return buildPage($title, $header, $section); +} + +function buildHeader($e, $bridge){ + return << +

Error {$e->getCode()}

+

{$e->getMessage()}

+

{$bridge->getName()}

+ +EOD; +} + +function buildSection($e, $bridge, $message, $link){ + return << +

{$message}

+
+
    +
  • Press Return to check your input parameters
  • +
  • Press F5 to retry
  • +
  • Open a GitHub Issue if this error persists
  • +
+
+ +

{$bridge->getMaintainer()}

+ +EOD; +} + +function buildPage($title, $header, $section){ + return << + + + {$title} + + + + {$header} + {$section} + + +EOD; +} diff --git a/static/style.css b/static/style.css index bade93f..d477588 100644 --- a/static/style.css +++ b/static/style.css @@ -244,3 +244,37 @@ h5 { display: block; } + +/* Additional styles for error pages */ + +.exception-message { + + background-color: #c00000; + color: #FFFFFF; + + font-weight: bold; + + box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.3); + border-radius: 2px; + border: 1px solid transparent; + + width: 80%; + margin: auto; + margin-bottom: 6px; + +} + +.advice { + + margin-left: auto; + margin-right: auto; + + display: table; + +} + +.advice > li { + + text-align: left; + +}