Skip to content

Commit b634629

Browse files
Vitexusclaude
andcommitted
fix: use curl with connect+total timeouts for mServer connection test
Replace file_get_contents (socket read timeout only) with curl so that CURLOPT_CONNECTTIMEOUT=5 and CURLOPT_TIMEOUT=10 are both enforced. This prevents the web page from hanging when mServer is unreachable or frozen. Add humanized error messages for timeout, connection refused, unresolvable host and empty response. Show a warning badge when the server reports status=busy or processing>0. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent e8dbc63 commit b634629

2 files changed

Lines changed: 61 additions & 20 deletions

File tree

debian/changelog

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
multiflexi-mserver (1.2.1) unstable; urgency=medium
2+
3+
* fix: replace file_get_contents with curl in UI connection test
4+
* fix: add CURLOPT_CONNECTTIMEOUT=5 and CURLOPT_TIMEOUT=10 to handle
5+
frozen/unreachable mServer without hanging the web page
6+
* fix: humanize curl error codes (timeout, refused, unresolvable host,
7+
no response) into user-readable messages
8+
* fix: show warning when mServer responds with status=busy or processing>0
9+
10+
-- Vítězslav Dvořák <info@vitexsoftware.cz> Mon, 26 May 2026 14:00:00 +0200
11+
112
multiflexi-mserver (1.2.0) unstable; urgency=medium
213

314
* feat: add smart credential prototype PHP classes (CredentialProtoType and Ui)

src/MultiFlexi/Ui/CredentialType/MServer.php

Lines changed: 50 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,19 @@ public function finalize(): void
8989
)));
9090

9191
if (!empty($result['info'])) {
92-
$serverPanel = new \Ease\TWB4\Panel(_('Server Status'), 'info');
92+
$panelType = 'info';
93+
$processing = (int) ($result['raw']['processing'] ?? 0);
94+
$status = $result['raw']['status'] ?? '';
95+
96+
if ($processing > 0 || $status === 'busy') {
97+
$this->addItem(new \Ease\TWB4\Alert('warning', sprintf(
98+
_('mServer is busy (processing: %d) — server may be frozen or under heavy load'),
99+
$processing,
100+
)));
101+
$panelType = 'warning';
102+
}
103+
104+
$serverPanel = new \Ease\TWB4\Panel(_('Server Status'), $panelType);
93105
$serverList = new \Ease\Html\DlTag(null, ['class' => 'row']);
94106

95107
foreach ($result['info'] as $key => $value) {
@@ -111,40 +123,54 @@ public function finalize(): void
111123
parent::finalize();
112124
}
113125

126+
/**
127+
* Translate a curl error code into a human-readable message.
128+
*/
129+
private static function humanizeCurlError(int $errno, string $url): string
130+
{
131+
return match ($errno) {
132+
\CURLE_COULDNT_CONNECT => sprintf(_('Cannot connect to mServer at %s — server may be down or firewall is blocking the port'), $url),
133+
\CURLE_OPERATION_TIMEDOUT => sprintf(_('mServer at %s is not responding (timeout) — server may be frozen'), $url),
134+
\CURLE_COULDNT_RESOLVE_HOST => sprintf(_('Cannot resolve hostname in %s — check POHODA_URL'), $url),
135+
\CURLE_GOT_NOTHING => sprintf(_('mServer at %s accepted the connection but sent no response — server may be frozen'), $url),
136+
default => sprintf(_('Connection to %s failed'), $url),
137+
};
138+
}
139+
114140
/**
115141
* Test mServer /status endpoint with HTTP Basic Auth.
116142
*
117-
* @return array{success: bool, message: string, info: array<string, string>}
143+
* Uses curl so that both connect timeout and total request timeout are
144+
* enforced — file_get_contents only has a socket read timeout and can
145+
* block for the full OS TCP handshake time when mServer is unreachable.
146+
*
147+
* @return array{success: bool, message: string, info: array<string, string>, raw: array<string, string>}
118148
*/
119149
private static function testConnection(string $statusUrl, string $username, string $password): array
120150
{
121-
$context = stream_context_create([
122-
'http' => [
123-
'method' => 'GET',
124-
'header' => 'Authorization: Basic '.base64_encode($username.':'.$password)."\r\n",
125-
'timeout' => 10,
126-
'ignore_errors' => true,
127-
],
151+
$ch = curl_init($statusUrl);
152+
curl_setopt_array($ch, [
153+
\CURLOPT_RETURNTRANSFER => true,
154+
\CURLOPT_HTTPAUTH => \CURLAUTH_BASIC,
155+
\CURLOPT_USERPWD => $username.':'.$password,
156+
\CURLOPT_CONNECTTIMEOUT => 5,
157+
\CURLOPT_TIMEOUT => 10,
158+
\CURLOPT_FOLLOWLOCATION => false,
128159
]);
129160

130-
$response = @file_get_contents($statusUrl, false, $context);
161+
$response = curl_exec($ch);
162+
$httpStatus = (int) curl_getinfo($ch, \CURLINFO_HTTP_CODE);
163+
$curlErrno = curl_errno($ch);
164+
curl_close($ch);
131165

132-
if ($response === false) {
166+
if ($response === false || $curlErrno !== 0) {
133167
return [
134168
'success' => false,
135-
'message' => error_get_last()['message'] ?? _('Connection failed'),
169+
'message' => self::humanizeCurlError($curlErrno, $statusUrl),
136170
'info' => [],
137171
];
138172
}
139173

140-
$httpStatus = 0;
141-
142-
if (isset($http_response_header) && \is_array($http_response_header)) {
143-
if (preg_match('#HTTP/\S+\s+(\d+)#', $http_response_header[0], $m)) {
144-
$httpStatus = (int) $m[1];
145-
}
146-
}
147-
148174
if ($httpStatus === 401) {
149175
return [
150176
'success' => false,
@@ -162,6 +188,7 @@ private static function testConnection(string $statusUrl, string $username, stri
162188
}
163189

164190
$info = [];
191+
$raw = [];
165192

166193
$xml = @simplexml_load_string($response);
167194

@@ -171,10 +198,12 @@ private static function testConnection(string $statusUrl, string $username, stri
171198
}
172199

173200
if (isset($xml->status)) {
201+
$raw['status'] = (string) $xml->status;
174202
$info[_('Status')] = (string) $xml->status;
175203
}
176204

177205
if (isset($xml->processing)) {
206+
$raw['processing'] = (string) $xml->processing;
178207
$info[_('Processing')] = (string) $xml->processing;
179208
}
180209

@@ -191,6 +220,7 @@ private static function testConnection(string $statusUrl, string $username, stri
191220
'success' => true,
192221
'message' => '',
193222
'info' => $info,
223+
'raw' => $raw,
194224
];
195225
}
196226
}

0 commit comments

Comments
 (0)