From 9ce010f5c1c394c35a9a25f89cd1b2cba3904c23 Mon Sep 17 00:00:00 2001 From: Panfilov Konstantin Date: Mon, 5 Oct 2026 15:03:29 +0300 Subject: [PATCH] =?UTF-8?q?=D0=97=D0=B0=D0=B3=D1=80=D1=83=D0=B7=D0=BA?= =?UTF-8?q?=D0=B0:=20client=5Fkey=20=D0=B8=20=D0=BF=D0=B5=D1=80=D0=B5?= =?UTF-8?q?=D1=85=D0=BE=D0=B4=20=D0=BD=D0=B0=20/api/images/public/claim=20?= =?UTF-8?q?=D0=B2=D0=BC=D0=B5=D1=81=D1=82=D0=BE=20/public/upscale?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit После загрузки посетитель попадал на /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 --- components/form.php | 10 ++++++++-- index.php | 4 +++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/components/form.php b/components/form.php index b0e41a3..a982291 100644 --- a/components/form.php +++ b/components/form.php @@ -197,7 +197,13 @@ $redirectUrlUtm = $redirect_url_utm ?? ''; function uploadFile(file) { const xhr = new XMLHttpRequest(); const formData = new FormData(); + // Ключ загрузки: по нему сайт передаёт её в сессию посетителя (/api/images/public/claim, годен 30 мин). + // randomUUID есть в HTTPS-контексте; где его нет (старый Safari), есть getRandomValues. + const clientKey = crypto.randomUUID + ? crypto.randomUUID() + : Array.from(crypto.getRandomValues(new Uint8Array(16)), (b) => b.toString(16).padStart(2, '0')).join(''); formData.append('file', file); + formData.append('client_key', clientKey); const actionUrl = createApiUrl || formEl.getAttribute('action') || '/api/images/public/create'; xhr.open('POST', actionUrl, true); @@ -232,8 +238,8 @@ $redirectUrlUtm = $redirect_url_utm ?? ''; process.setStage(1); } - // Build redirect target URL: $redirect_url_base . $imageId . ($redirect_url_utm ? '&' . $redirect_url_utm : '') - let targetUrl = redirectUrlBase + encodeURIComponent(imageId); + // Переход: $redirect_url_base . client_key . ($redirect_url_utm ? '&' . $redirect_url_utm : '') + let targetUrl = redirectUrlBase + encodeURIComponent(clientKey); if (redirectUrlUtm) { // const sep = targetUrl.includes('?') ? '&' : '?'; targetUrl += '&' + redirectUrlUtm; diff --git a/index.php b/index.php index e01b29f..61c71ee 100644 --- a/index.php +++ b/index.php @@ -71,7 +71,9 @@ $UTM = $get_params; $host = $config['host'] ?? ($_SERVER['HTTP_HOST'] ?? ''); $apiHost = $host ? (preg_match('#^https?://#', $host) ? rtrim($host, '/') : 'https://' . rtrim($host, '/')) : ''; -$redirect_url_base = ($apiHost ? $apiHost : '') . '/public/upscale?id='; +// После загрузки — на сайт по ключу загрузки (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'] ?? '';