Улучшена загрузка метаданных wishlist
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 56s
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 56s
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "play-life-web",
|
||||
"version": "3.10.6",
|
||||
"version": "3.10.7",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user