rss-bridge/lib/Exceptions.php
LogMANOriginal 38b56bf23a [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
2017-07-29 19:16:16 +02:00

209 lines
5.5 KiB
PHP

<?php
class HttpException extends \Exception{}
/**
* Not real http implementation but only utils stuff
*/
class Http{
/**
* Return message corresponding to Http code
*/
static public function getMessageForCode($code){
$codes = self::getCodes();
if(isset($codes[$code]))
return $codes[$code];
return '';
}
/**
* List of common Http code
*/
static public function getCodes(){
return array(
200 => 'OK',
201 => 'Created',
202 => 'Accepted',
300 => 'Multiple Choices',
301 => 'Moved Permanently',
302 => 'Moved Temporarily',
307 => 'Temporary Redirect',
310 => 'Too many Redirects',
400 => 'Bad Request',
401 => 'Unauthorized',
402 => 'Payment Required',
403 => 'Forbidden',
404 => 'Not Found',
405 => 'Method Not',
406 => 'Not Acceptable',
407 => 'Proxy Authentication Required',
408 => 'Request Time-out',
409 => 'Conflict',
410 => 'Gone',
411 => 'Length Required',
412 => 'Precondition Failed',
413 => 'Request Entity Too Large',
414 => 'Request-URI Too Long',
415 => 'Unsupported Media Type',
416 => 'Requested range unsatisfiable',
417 => 'Expectation failed',
500 => 'Internal Server Error',
501 => 'Not Implemented',
502 => 'Bad Gateway',
503 => 'Service Unavailable',
504 => 'Gateway Time-out',
508 => 'Loop detected',
);
}
}
/**
* 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 = "<strong>{$bridge->getName()}</strong> 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
<strong>{$bridge->getName()}</strong>!";
$section = buildSection($e, $bridge, $message, $link);
return buildPage($title, $header, $section);
}
function buildHeader($e, $bridge){
return <<<EOD
<header>
<h1>Error {$e->getCode()}</h1>
<h2>{$e->getMessage()}</h2>
<p class="status">{$bridge->getName()}</p>
</header>
EOD;
}
function buildSection($e, $bridge, $message, $link){
return <<<EOD
<section>
<p class="exception-message">{$message}</p>
<div class="advice">
<ul class="advice">
<li>Press Return to check your input parameters</li>
<li>Press F5 to retry</li>
<li>Open a GitHub Issue if this error persists</li>
</ul>
</div>
<a href="{$link}" title="After clicking this button you can review
the issue before submitting it"><button>Open GitHub Issue</button></a>
<p class="maintainer">{$bridge->getMaintainer()}</p>
</section>
EOD;
}
function buildPage($title, $header, $section){
return <<<EOD
<!DOCTYPE html>
<html lang="en">
<head>
<title>{$title}</title>
<link href="static/style.css" rel="stylesheet">
</head>
<body>
{$header}
{$section}
</body>
</html>
EOD;
}