From 5af14c8d80c128d685bf9f418fc4d676f9e40445 Mon Sep 17 00:00:00 2001 From: nethunterzist Date: Mon, 4 May 2026 11:43:15 +0300 Subject: [PATCH] fix(api): category-tree endpoint'lerini public yap (revert+fix encoding corruption) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ne yaptık: - PUBLIC_PATHS setine /api/category-tree, /api/category-tree/roots, /api/category-tree/search eklendi - Önceki commit base64 round-trip nedeniyle dosyayı bozmuştu, bu commit doğru encoding ile yazıldı Neden yaptık: - API_KEY env var set olduğunda tüm endpoint'ler auth gerektiriyor - Frontend X-API-Key header göndermiyordu → 401 → 'Kategoriler yükleniyor...' - Category tree read-only, herkese açık veri — auth gerekmez --- backend/main.py | 76 +++++++++++++------------------------------------ 1 file changed, 19 insertions(+), 57 deletions(-) diff --git a/backend/main.py b/backend/main.py index b96c2fe..e0ff5a5 100644 --- a/backend/main.py +++ b/backend/main.py @@ -1667,19 +1667,13 @@ async def create_report( log_sse.info(f"SSE stream started: task={task_id}, category={main_cat_name}") try: # Send initial info - yield f"data: {json_module.dumps({'type': 'info', 'message': f'📂 {main_cat_name} kategorisi seçildi', 'progress': 0})} - -" + yield f"data: {json_module.dumps({'type': 'info', 'message': f'📂 {main_cat_name} kategorisi seçildi', 'progress': 0})}\n\n" await asyncio.sleep(0.1) - yield f"data: {json_module.dumps({'type': 'info', 'message': f'📊 {len(categories_to_scrape)} alt kategori bulundu', 'progress': 0})} - -" + yield f"data: {json_module.dumps({'type': 'info', 'message': f'📊 {len(categories_to_scrape)} alt kategori bulundu', 'progress': 0})}\n\n" await asyncio.sleep(0.1) - yield f"data: {json_module.dumps({'type': 'info', 'message': '🚀 Veri çekimi başlatılıyor...', 'progress': 5})} - -" + yield f"data: {json_module.dumps({'type': 'info', 'message': '🚀 Veri çekimi başlatılıyor...', 'progress': 5})}\n\n" await asyncio.sleep(0.5) # Start synchronous scraping with progress updates @@ -1700,17 +1694,13 @@ async def create_report( for idx, (path_model, cat_name, cat_id) in enumerate(categories_to_scrape, 1): progress = int((idx / len(categories_to_scrape)) * 80) + 10 - yield f"data: {json_module.dumps({'type': 'processing', 'message': f'🔍 [{idx}/{len(categories_to_scrape)}] {cat_name} çekiliyor...', 'progress': progress, 'current': idx, 'total': len(categories_to_scrape)})} - -" + yield f"data: {json_module.dumps({'type': 'processing', 'message': f'🔍 [{idx}/{len(categories_to_scrape)}] {cat_name} çekiliyor...', 'progress': progress, 'current': idx, 'total': len(categories_to_scrape)})}\n\n" await asyncio.sleep(0.1) try: if path_model: # New Search API — works for both -c and -s categories - yield f"data: {json_module.dumps({'type': 'api', 'message': f'🌐 API: Trendyol Search - {path_model}', 'progress': progress})} - -" + yield f"data: {json_module.dumps({'type': 'api', 'message': f'🌐 API: Trendyol Search - {path_model}', 'progress': progress})}\n\n" await asyncio.sleep(0.1) scraper = TrendyolSearchScraper(path_model) @@ -1742,9 +1732,7 @@ async def create_report( elif cat_id: # Legacy fallback — old top-rankings API - yield f"data: {json_module.dumps({'type': 'api', 'message': f'🌐 API: Trendyol Best Seller - Kategori ID: {cat_id}', 'progress': progress})} - -" + yield f"data: {json_module.dumps({'type': 'api', 'message': f'🌐 API: Trendyol Best Seller - Kategori ID: {cat_id}', 'progress': progress})}\n\n" await asyncio.sleep(0.1) scraper = TrendyolScraper(cat_id) @@ -1780,9 +1768,7 @@ async def create_report( "file_path": filename }) - yield f"data: {json_module.dumps({'type': 'success', 'message': f'✅ {cat_name} tamamlandı - {len(products)} ürün bulundu', 'progress': progress})} - -" + yield f"data: {json_module.dumps({'type': 'success', 'message': f'✅ {cat_name} tamamlandı - {len(products)} ürün bulundu', 'progress': progress})}\n\n" await asyncio.sleep(0.1) else: results["failed"] += 1 @@ -1794,9 +1780,7 @@ async def create_report( "total_products": 0, "file_path": None }) - yield f"data: {json_module.dumps({'type': 'warning', 'message': f'⚠️ {cat_name} - Ürün bulunamadı', 'progress': progress})} - -" + yield f"data: {json_module.dumps({'type': 'warning', 'message': f'⚠️ {cat_name} - Ürün bulunamadı', 'progress': progress})}\n\n" await asyncio.sleep(0.1) except Exception as e: @@ -1809,18 +1793,14 @@ async def create_report( "total_products": 0, "file_path": None }) - yield f"data: {json_module.dumps({'type': 'error', 'message': f'❌ {cat_name} - Hata: {str(e)}', 'progress': progress})} - -" + yield f"data: {json_module.dumps({'type': 'error', 'message': f'❌ {cat_name} - Hata: {str(e)}', 'progress': progress})}\n\n" await asyncio.sleep(0.1) # Rate limiting (non-blocking) await asyncio.sleep(1.5) # Generate report file - yield f"data: {json_module.dumps({'type': 'info', 'message': '📝 Rapor dosyası oluşturuluyor...', 'progress': 88})} - -" + yield f"data: {json_module.dumps({'type': 'info', 'message': '📝 Rapor dosyası oluşturuluyor...', 'progress': 88})}\n\n" await asyncio.sleep(0.5) timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") @@ -1842,9 +1822,7 @@ async def create_report( await asyncio.to_thread(_write_json, json_filename, combined_data) # Save to database - yield f"data: {json_module.dumps({'type': 'info', 'message': '💾 Veritabanına kaydediliyor...', 'progress': 93})} - -" + yield f"data: {json_module.dumps({'type': 'info', 'message': '💾 Veritabanına kaydediliyor...', 'progress': 93})}\n\n" await asyncio.sleep(0.5) new_report = Report( @@ -1878,9 +1856,7 @@ async def create_report( log_sse.info(f"Background enrichment started for report {report_id_for_enrich}") # Wait for enrichment to complete, sending progress updates via SSE - yield f"data: {json_module.dumps({'type': 'info', 'message': '📊 Sosyal kanıt verileri toplanıyor...', 'progress': 90})} - -" + yield f"data: {json_module.dumps({'type': 'info', 'message': '📊 Sosyal kanıt verileri toplanıyor...', 'progress': 90})}\n\n" await asyncio.sleep(0.5) progress_key = f"social_{report_id_for_enrich}" @@ -1898,38 +1874,26 @@ async def create_report( if sp_total > 0: overall_pct = 90 + int(sp_pct * 0.09) - yield f"data: {json_module.dumps({'type': 'info', 'message': f'📊 Sosyal kanıt: {sp_processed}/{sp_total} ürün (%{sp_pct})', 'progress': overall_pct})} - -" + yield f"data: {json_module.dumps({'type': 'info', 'message': f'📊 Sosyal kanıt: {sp_processed}/{sp_total} ürün (%{sp_pct})', 'progress': overall_pct})}\n\n" await asyncio.sleep(3) waited += 3 enrich_status = enrichment_progress.get(report_id_for_enrich) or {} if enrich_status.get("status") == "completed": - yield f"data: {json_module.dumps({'type': 'info', 'message': '✅ Sosyal kanıt tamamlandı!', 'progress': 99})} - -" + yield f"data: {json_module.dumps({'type': 'info', 'message': '✅ Sosyal kanıt tamamlandı!', 'progress': 99})}\n\n" elif enrich_status.get("status") == "error": err_msg = str(enrich_status.get("error", ""))[:100] - yield f"data: {json_module.dumps({'type': 'warning', 'message': f'⚠️ Sosyal kanıt hatası: {err_msg}', 'progress': 99})} - -" + yield f"data: {json_module.dumps({'type': 'warning', 'message': f'⚠️ Sosyal kanıt hatası: {err_msg}', 'progress': 99})}\n\n" else: - yield f"data: {json_module.dumps({'type': 'warning', 'message': '⚠️ Sosyal kanıt zaman aşımı, arka planda devam ediyor...', 'progress': 99})} - -" + yield f"data: {json_module.dumps({'type': 'warning', 'message': '⚠️ Sosyal kanıt zaman aşımı, arka planda devam ediyor...', 'progress': 99})}\n\n" else: - yield f"data: {json_module.dumps({'type': 'info', 'message': '📊 Rapor JSON olarak kaydedildi (DB atlandı)', 'progress': 99})} - -" + yield f"data: {json_module.dumps({'type': 'info', 'message': '📊 Rapor JSON olarak kaydedildi (DB atlandı)', 'progress': 99})}\n\n" await asyncio.sleep(0.1) # Final success message - yield f"data: {json_module.dumps({'type': 'complete', 'message': '✅ Rapor başarıyla oluşturuldu!', 'progress': 100, 'report_id': report_id_for_enrich, 'total_products': results['total_products'], 'successful': results['successful'], 'enrichment_status': enrich_status.get('status', 'unknown')})} - -" + yield f"data: {json_module.dumps({'type': 'complete', 'message': '✅ Rapor başarıyla oluşturuldu!', 'progress': 100, 'report_id': report_id_for_enrich, 'total_products': results['total_products'], 'successful': results['successful'], 'enrichment_status': enrich_status.get('status', 'unknown')})}\n\n" await asyncio.sleep(0.1) except asyncio.CancelledError: @@ -1937,9 +1901,7 @@ async def create_report( return except Exception as e: log_sse.error(f"SSE stream error: task={task_id}, error={e}", exc_info=True) - yield f"data: {json_module.dumps({'type': 'error', 'message': f'❌ Kritik hata: {str(e)}', 'progress': -1})} - -" + yield f"data: {json_module.dumps({'type': 'error', 'message': f'❌ Kritik hata: {str(e)}', 'progress': -1})}\n\n" return StreamingResponse(progress_stream(), media_type="text/event-stream")