Files
preland/index.php
T
Panfilov KonstantinandClaude Opus 5.5 9ce010f5c1 Загрузка: client_key и переход на /api/images/public/claim вместо /public/upscale
После загрузки посетитель попадал на /public/upscale?id=… и видел 404: XHR с преленда кросс-доменный, и сессия,
в которой сайт запомнил загрузку, посетителю на сайте недоступна (куки третьей стороны изолированы или не приняты).
Теперь вместе с файлом уходит client_key (crypto.randomUUID, иначе 16 байт getRandomValues), а после ответа браузер
идёт на https://<сайт>/api/images/public/claim?key=<ключ>&<метки>: сайт кладёт загрузку в сессию посетителя
и ведёт на /public/upscale (ключ годен 30 мин). Нужен api с ClaimAction (fix/preland-claim).

Проверка — .extras/checks-preland-claim/t_preland.sh в рабочей области (index.php в php:8.3-cli, скрипт формы
в node:22): до правки FAIL=3, после 5/5.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 15:03:29 +03:00

110 lines
3.6 KiB
PHP

<?php
require_once __DIR__ . '/i18n.php';
$configFile = __DIR__ . '/config.json';
$config = file_exists($configFile) ? json_decode(file_get_contents($configFile), true) : [];
if (json_last_error() !== JSON_ERROR_NONE) {
throw new RuntimeException('JSON syntax error: ' . json_last_error_msg());
}
Yii::init($config['default_language'] ?? 'ru');
function getWeightedRandom($weights)
{
if (empty($weights)) {
return '';
}
$totalWeight = array_sum($weights);
if ($totalWeight <= 0) {
$keys = array_keys($weights);
return (string)$keys[0];
}
$rand = (mt_rand() / mt_getrandmax()) * $totalWeight;
$current = 0.0;
foreach ($weights as $key => $weight) {
$current += (float)$weight;
if ($rand <= $current) {
return (string)$key;
}
}
$keys = array_keys($weights);
return (string)end($keys);
}
$get_params = $_GET;
if (isset($config['utm']) && is_array($config['utm'])) {
foreach ($get_params as $key => $value) {
if (!isset($config['utm'][$key])) {
continue;
}
if (isset($config['utm'][$key]['weights'][$value])) {
continue;
}
if ($value !== 'rnd') {
unset($get_params[$key]);
continue;
}
$weights = $config['utm'][$key]['weights'] ?? [];
$get_params[$key] = getWeightedRandom($weights);
}
foreach ($config['utm'] as $key => $value) {
if (isset($get_params[$key])) {
continue;
}
$get_params[$key] = $config['utm'][$key]['default'];
}
}
$UTM = $get_params;
$host = $config['host'] ?? ($_SERVER['HTTP_HOST'] ?? '');
$apiHost = $host ? (preg_match('#^https?://#', $host) ? rtrim($host, '/') : 'https://' . rtrim($host, '/')) : '';
// После загрузки — на сайт по ключу загрузки (client_key): /api/images/public/claim кладёт её в сессию посетителя и ведёт
// на /public/upscale. Сразу на /public/upscale нельзя: сессия кросс-доменной загрузки посетителю на сайте недоступна — 404.
$redirect_url_base = ($apiHost ? $apiHost : '') . '/api/images/public/claim?key=';
$redirect_url_utm = http_build_query($get_params);
$assetsUriPrefix = $config['assetsUriPrefix'] ?? '';
if ($assetsUriPrefix === '' && !is_dir(__DIR__ . '/images') && !empty($apiHost)) {
$assetsUriPrefix = $apiHost;
}
$fontsUrl = $config['fontsUrl'] ?? ($assetsUriPrefix ? $assetsUriPrefix . '/fonts' : 'fonts');
$favicon = (object)[
'baseUrl' => $config['faviconUrl'] ?? ($assetsUriPrefix ? $assetsUriPrefix . '/favicon' : 'favicon')
];
$logoAltExt = $config['logoAltExt'] ?? 'svg';
$spritePath = $config['spritePath'] ?? ($assetsUriPrefix ? $assetsUriPrefix . '/images/sprite.svg' : 'images/sprite.svg');
$default_title = $config['title'] ?? 'Улучшение изображения';
$indpic = isset($UTM['indpic']) && preg_match('/^[a-zA-Z0-9_-]+$/', (string)$UTM['indpic'])
? (string)$UTM['indpic']
: ($config['utm']['indpic']['default'] ?? '2');
function renderComponent(string $name, array $params = []): void
{
global $assetsUriPrefix, $fontsUrl, $favicon, $logoAltExt, $spritePath, $UTM, $config, $indpic, $apiHost, $redirect_url_base, $redirect_url_utm;
extract($params, EXTR_SKIP);
$componentFile = __DIR__ . '/components/' . $name . '.php';
if (file_exists($componentFile)) {
require $componentFile;
}
}
require_once __DIR__ . '/template.php';
?>
<style>
<?= file_get_contents(__DIR__ . '/style.min.css'); ?>
</style>