fix: prefer healthy native media edges
This commit is contained in:
Vendored
+35
-4
@@ -61,6 +61,27 @@ function mediaProxyCacheRoot(): string
|
||||
return $root;
|
||||
}
|
||||
|
||||
function mediaProxyPreferredIps(): array
|
||||
{
|
||||
$configured = preg_split('/[,\s]+/', webImEnv('JC_WEB_IM_MEDIA_PROXY_IPS')) ?: [];
|
||||
$ips = [];
|
||||
foreach ($configured as $ip) {
|
||||
$ip = trim($ip);
|
||||
if (
|
||||
$ip !== ''
|
||||
&& filter_var(
|
||||
$ip,
|
||||
FILTER_VALIDATE_IP,
|
||||
FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE
|
||||
) !== false
|
||||
) {
|
||||
$ips[$ip] = $ip;
|
||||
}
|
||||
}
|
||||
|
||||
return array_values($ips);
|
||||
}
|
||||
|
||||
function mediaProxyMime(string $path): string
|
||||
{
|
||||
$finfo = finfo_open(FILEINFO_MIME_TYPE);
|
||||
@@ -76,8 +97,14 @@ function fetchMediaProxyImage(string $url, string $host, string $cacheFile): voi
|
||||
{
|
||||
$deadline = microtime(true) + WEB_MEDIA_PROXY_MAX_SECONDS;
|
||||
$lastError = '媒体源无响应';
|
||||
$preferredIps = mediaProxyPreferredIps();
|
||||
$targets = array_merge($preferredIps, array_fill(0, max(2, 6 - count($preferredIps)), null));
|
||||
|
||||
for ($attempt = 1; $attempt <= 6 && microtime(true) < $deadline; $attempt++) {
|
||||
foreach ($targets as $index => $preferredIp) {
|
||||
if (microtime(true) >= $deadline) {
|
||||
break;
|
||||
}
|
||||
$attempt = $index + 1;
|
||||
$temporaryFile = $cacheFile . '.tmp.' . getmypid() . '.' . $attempt;
|
||||
$stream = @fopen($temporaryFile, 'x+b');
|
||||
if ($stream === false) {
|
||||
@@ -96,7 +123,7 @@ function fetchMediaProxyImage(string $url, string $host, string $cacheFile): voi
|
||||
}
|
||||
|
||||
$remainingMs = max(1000, (int)floor(($deadline - microtime(true)) * 1000));
|
||||
curl_setopt_array($curl, [
|
||||
$curlOptions = [
|
||||
CURLOPT_RETURNTRANSFER => false,
|
||||
CURLOPT_FOLLOWLOCATION => false,
|
||||
CURLOPT_CONNECTTIMEOUT_MS => min(2500, $remainingMs),
|
||||
@@ -123,7 +150,11 @@ function fetchMediaProxyImage(string $url, string $host, string $cacheFile): voi
|
||||
$bytes += $written;
|
||||
return $written;
|
||||
},
|
||||
]);
|
||||
];
|
||||
if (is_string($preferredIp) && $preferredIp !== '') {
|
||||
$curlOptions[CURLOPT_RESOLVE] = [$host . ':443:' . $preferredIp];
|
||||
}
|
||||
curl_setopt_array($curl, $curlOptions);
|
||||
|
||||
$result = curl_exec($curl);
|
||||
$status = (int)curl_getinfo($curl, CURLINFO_RESPONSE_CODE);
|
||||
@@ -147,7 +178,7 @@ function fetchMediaProxyImage(string $url, string $host, string $cacheFile): voi
|
||||
$lastError = $tooLarge
|
||||
? '图片超过代理大小限制'
|
||||
: ($curlError !== '' ? $curlError : ($status > 0 ? '媒体源返回 HTTP ' . $status : '媒体源无响应'));
|
||||
if ($attempt < 6 && microtime(true) < $deadline) {
|
||||
if ($attempt < count($targets) && microtime(true) < $deadline) {
|
||||
usleep(150000);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,6 +61,27 @@ function mediaProxyCacheRoot(): string
|
||||
return $root;
|
||||
}
|
||||
|
||||
function mediaProxyPreferredIps(): array
|
||||
{
|
||||
$configured = preg_split('/[,\s]+/', webImEnv('JC_WEB_IM_MEDIA_PROXY_IPS')) ?: [];
|
||||
$ips = [];
|
||||
foreach ($configured as $ip) {
|
||||
$ip = trim($ip);
|
||||
if (
|
||||
$ip !== ''
|
||||
&& filter_var(
|
||||
$ip,
|
||||
FILTER_VALIDATE_IP,
|
||||
FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE
|
||||
) !== false
|
||||
) {
|
||||
$ips[$ip] = $ip;
|
||||
}
|
||||
}
|
||||
|
||||
return array_values($ips);
|
||||
}
|
||||
|
||||
function mediaProxyMime(string $path): string
|
||||
{
|
||||
$finfo = finfo_open(FILEINFO_MIME_TYPE);
|
||||
@@ -76,8 +97,14 @@ function fetchMediaProxyImage(string $url, string $host, string $cacheFile): voi
|
||||
{
|
||||
$deadline = microtime(true) + WEB_MEDIA_PROXY_MAX_SECONDS;
|
||||
$lastError = '媒体源无响应';
|
||||
$preferredIps = mediaProxyPreferredIps();
|
||||
$targets = array_merge($preferredIps, array_fill(0, max(2, 6 - count($preferredIps)), null));
|
||||
|
||||
for ($attempt = 1; $attempt <= 6 && microtime(true) < $deadline; $attempt++) {
|
||||
foreach ($targets as $index => $preferredIp) {
|
||||
if (microtime(true) >= $deadline) {
|
||||
break;
|
||||
}
|
||||
$attempt = $index + 1;
|
||||
$temporaryFile = $cacheFile . '.tmp.' . getmypid() . '.' . $attempt;
|
||||
$stream = @fopen($temporaryFile, 'x+b');
|
||||
if ($stream === false) {
|
||||
@@ -96,7 +123,7 @@ function fetchMediaProxyImage(string $url, string $host, string $cacheFile): voi
|
||||
}
|
||||
|
||||
$remainingMs = max(1000, (int)floor(($deadline - microtime(true)) * 1000));
|
||||
curl_setopt_array($curl, [
|
||||
$curlOptions = [
|
||||
CURLOPT_RETURNTRANSFER => false,
|
||||
CURLOPT_FOLLOWLOCATION => false,
|
||||
CURLOPT_CONNECTTIMEOUT_MS => min(2500, $remainingMs),
|
||||
@@ -123,7 +150,11 @@ function fetchMediaProxyImage(string $url, string $host, string $cacheFile): voi
|
||||
$bytes += $written;
|
||||
return $written;
|
||||
},
|
||||
]);
|
||||
];
|
||||
if (is_string($preferredIp) && $preferredIp !== '') {
|
||||
$curlOptions[CURLOPT_RESOLVE] = [$host . ':443:' . $preferredIp];
|
||||
}
|
||||
curl_setopt_array($curl, $curlOptions);
|
||||
|
||||
$result = curl_exec($curl);
|
||||
$status = (int)curl_getinfo($curl, CURLINFO_RESPONSE_CODE);
|
||||
@@ -147,7 +178,7 @@ function fetchMediaProxyImage(string $url, string $host, string $cacheFile): voi
|
||||
$lastError = $tooLarge
|
||||
? '图片超过代理大小限制'
|
||||
: ($curlError !== '' ? $curlError : ($status > 0 ? '媒体源返回 HTTP ' . $status : '媒体源无响应'));
|
||||
if ($attempt < 6 && microtime(true) < $deadline) {
|
||||
if ($attempt < count($targets) && microtime(true) < $deadline) {
|
||||
usleep(150000);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user