From 0783602fe8ef47fcb29237de1cd2874916044650 Mon Sep 17 00:00:00 2001 From: poignatov Date: Tue, 13 Jan 2026 17:19:00 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A3=D0=BB=D1=83=D1=87=D1=88=D0=B5=D0=BD?= =?UTF-8?q?=D0=B0=20=D0=B7=D0=B0=D0=B3=D1=80=D1=83=D0=B7=D0=BA=D0=B0=20?= =?UTF-8?q?=D0=BC=D0=B5=D1=82=D0=B0=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20?= =?UTF-8?q?wishlist?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- VERSION | 2 +- play-life-backend/main.go | 54 +++++++++++++++---- play-life-web/package.json | 2 +- play-life-web/src/components/WishlistForm.jsx | 24 ++++++++- 4 files changed, 69 insertions(+), 13 deletions(-) diff --git a/VERSION b/VERSION index ac957df..1281604 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.10.6 +3.10.7 diff --git a/play-life-backend/main.go b/play-life-backend/main.go index 5c85d79..e94462e 100644 --- a/play-life-backend/main.go +++ b/play-life-backend/main.go @@ -9974,49 +9974,85 @@ func (a *App) extractLinkMetadataHandler(w http.ResponseWriter, r *http.Request) } if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + log.Printf("Error decoding metadata request body: %v", err) sendErrorWithCORS(w, "Invalid request body", http.StatusBadRequest) return } if req.URL == "" { + log.Printf("Empty URL in metadata request") sendErrorWithCORS(w, "URL is required", http.StatusBadRequest) return } + log.Printf("Extracting metadata for URL: %s", req.URL) + // Валидация URL parsedURL, err := url.Parse(req.URL) if err != nil || parsedURL.Scheme == "" || parsedURL.Host == "" { + log.Printf("Invalid URL format: %s, error: %v", req.URL, err) sendErrorWithCORS(w, "Invalid URL", http.StatusBadRequest) return } - // HTTP клиент с таймаутом + // HTTP клиент с увеличенным таймаутом и поддержкой редиректов + // Используем Transport с настройками для лучшей совместимости + transport := &http.Transport{ + DisableKeepAlives: false, + MaxIdleConns: 10, + IdleConnTimeout: 90 * time.Second, + } + client := &http.Client{ - Timeout: 10 * time.Second, + Timeout: 30 * time.Second, // Увеличиваем таймаут до 30 секунд + Transport: transport, + CheckRedirect: func(req *http.Request, via []*http.Request) error { + // Разрешаем до 10 редиректов + if len(via) >= 10 { + return fmt.Errorf("stopped after 10 redirects") + } + return nil + }, } httpReq, err := http.NewRequest("GET", req.URL, nil) if err != nil { - log.Printf("Error creating request: %v", err) + log.Printf("Error creating request for URL %s: %v", req.URL, err) sendErrorWithCORS(w, "Error creating request", http.StatusInternalServerError) return } - // Устанавливаем User-Agent (некоторые сайты блокируют запросы без него) - httpReq.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36") - httpReq.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8") + // Устанавливаем заголовки, имитирующие реальный браузер Chrome + httpReq.Header.Set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36") + httpReq.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7") httpReq.Header.Set("Accept-Language", "ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7") + httpReq.Header.Set("Accept-Encoding", "gzip, deflate, br") + httpReq.Header.Set("Connection", "keep-alive") + httpReq.Header.Set("Upgrade-Insecure-Requests", "1") + httpReq.Header.Set("Sec-Fetch-Dest", "document") + httpReq.Header.Set("Sec-Fetch-Mode", "navigate") + httpReq.Header.Set("Sec-Fetch-Site", "none") + httpReq.Header.Set("Sec-Fetch-User", "?1") + httpReq.Header.Set("Cache-Control", "max-age=0") + httpReq.Header.Set("DNT", "1") resp, err := client.Do(httpReq) if err != nil { - log.Printf("Error fetching URL: %v", err) + log.Printf("Error fetching URL %s: %v", req.URL, err) sendErrorWithCORS(w, fmt.Sprintf("Error fetching URL: %v", err), http.StatusBadRequest) return } defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - sendErrorWithCORS(w, fmt.Sprintf("HTTP %d", resp.StatusCode), http.StatusBadRequest) + // Логируем статус код для отладки + log.Printf("Fetched URL %s, status: %d", req.URL, resp.StatusCode) + + // Принимаем успешные статусы (200-299) и некоторые редиректы, которые могут содержать контент + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + // Для некоторых сайтов можно попробовать прочитать тело даже при не-200 статусе + // Но для большинства случаев это ошибка + log.Printf("Non-OK status code for URL %s: %d", req.URL, resp.StatusCode) + sendErrorWithCORS(w, fmt.Sprintf("HTTP %d: %s", resp.StatusCode, resp.Status), http.StatusBadRequest) return } diff --git a/play-life-web/package.json b/play-life-web/package.json index ff663c7..5abf9a0 100644 --- a/play-life-web/package.json +++ b/play-life-web/package.json @@ -1,6 +1,6 @@ { "name": "play-life-web", - "version": "3.10.6", + "version": "3.10.7", "type": "module", "scripts": { "dev": "vite", diff --git a/play-life-web/src/components/WishlistForm.jsx b/play-life-web/src/components/WishlistForm.jsx index 16c30c7..5cd11f5 100644 --- a/play-life-web/src/components/WishlistForm.jsx +++ b/play-life-web/src/components/WishlistForm.jsx @@ -220,11 +220,31 @@ function WishlistForm({ onNavigate, wishlistId, editConditionIndex }) { setToastMessage({ text: 'Не удалось найти информацию на странице', type: 'warning' }) } } else { - setToastMessage({ text: 'Не удалось загрузить информацию', type: 'error' }) + // Пытаемся получить детальное сообщение об ошибке + let errorMessage = 'Не удалось загрузить информацию' + try { + const errorData = await response.json() + errorMessage = errorData.message || errorData.error || errorMessage + } catch (e) { + const text = await response.text().catch(() => '') + if (text) { + try { + const parsed = JSON.parse(text) + errorMessage = parsed.message || parsed.error || errorMessage + } catch { + // Если не JSON, используем текст как есть (но обрезаем до разумной длины) + if (text.length < 200) { + errorMessage = text + } + } + } + } + setToastMessage({ text: errorMessage, type: 'error' }) } } catch (err) { console.error('Error fetching metadata:', err) - setToastMessage({ text: 'Ошибка при загрузке информации', type: 'error' }) + const errorMessage = err.message || 'Ошибка при загрузке информации' + setToastMessage({ text: errorMessage, type: 'error' }) } finally { setFetchingMetadata(false) }