Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pterodactyl
GitHub Repository: pterodactyl/panel
Path: blob/1.0-develop/app/Exceptions/Http/Connection/DaemonConnectionException.php
10284 views
1
<?php
2
3
namespace Pterodactyl\Exceptions\Http\Connection;
4
5
use Illuminate\Http\Response;
6
use Illuminate\Support\Facades\Log;
7
use GuzzleHttp\Exception\GuzzleException;
8
use Pterodactyl\Exceptions\DisplayException;
9
10
/**
11
* @method \GuzzleHttp\Exception\GuzzleException getPrevious()
12
*/
13
class DaemonConnectionException extends DisplayException
14
{
15
private int $statusCode = Response::HTTP_GATEWAY_TIMEOUT;
16
17
/**
18
* Every request to the Wings instance will return a unique X-Request-Id header
19
* which allows for all errors to be efficiently tied to a specific request that
20
* triggered them, and gives users a more direct method of informing hosts when
21
* something goes wrong.
22
*/
23
private ?string $requestId;
24
25
/**
26
* Throw a displayable exception caused by a daemon connection error.
27
*/
28
public function __construct(GuzzleException $previous, bool $useStatusCode = true)
29
{
30
/** @var \GuzzleHttp\Psr7\Response|null $response */
31
$response = method_exists($previous, 'getResponse') ? $previous->getResponse() : null;
32
$this->requestId = $response?->getHeaderLine('X-Request-Id');
33
34
if ($useStatusCode) {
35
$this->statusCode = is_null($response) ? $this->statusCode : $response->getStatusCode();
36
// There are rare conditions where wings encounters a panic condition and crashes the
37
// request being made after content has already been sent over the wire. In these cases
38
// you can end up with a "successful" response code that is actual an error.
39
//
40
// Handle those better here since we shouldn't ever end up in this exception state and
41
// be returning a 2XX level response.
42
if ($this->statusCode < 400) {
43
$this->statusCode = Response::HTTP_BAD_GATEWAY;
44
}
45
}
46
47
if (is_null($response)) {
48
$message = 'Could not establish a connection to the machine running this server. Please try again.';
49
} else {
50
$message = sprintf('There was an error while communicating with the machine running this server. This error has been logged, please try again. (code: %s) (request_id: %s)', $response->getStatusCode(), $this->requestId ?? '<nil>');
51
}
52
53
// Attempt to pull the actual error message off the response and return that if it is not
54
// a 500 level error.
55
if ($this->statusCode < 500 && !is_null($response)) {
56
$body = json_decode($response->getBody()->__toString(), true);
57
$message = sprintf('An error occurred on the remote host: %s. (request id: %s)', $body['error'] ?? $message, $this->requestId ?? '<nil>');
58
}
59
60
$level = $this->statusCode >= 500 && $this->statusCode !== 504
61
? DisplayException::LEVEL_ERROR
62
: DisplayException::LEVEL_WARNING;
63
64
parent::__construct($message, $previous, $level);
65
}
66
67
/**
68
* Override the default reporting method for DisplayException by just logging immediately
69
* here and including the specific X-Request-Id header that was returned by the call.
70
*/
71
public function report()
72
{
73
Log::{$this->getErrorLevel()}($this->getPrevious(), [
74
'request_id' => $this->requestId,
75
]);
76
}
77
78
/**
79
* Return the HTTP status code for this exception.
80
*/
81
public function getStatusCode(): int
82
{
83
return $this->statusCode;
84
}
85
86
public function getRequestId(): ?string
87
{
88
return $this->requestId;
89
}
90
}
91
92