Commit 9920f907 authored by nextime's avatar nextime

Enforce strict ID matching and complete JSON validation before serving responses

- Add comprehensive logging with emojis for better debugging visibility
- Implement strict validation requiring exact ID match and non-empty response
- Enhanced observer logic to only resolve on complete, validated JSON
- Add priority-based detection: HTML code blocks first, then text content
- Prevent premature response serving until complete JSON with matching ID is found
- Add detailed console logging for tracking detection progress
- Ensure system waits for complete ID match before serving any API response

This ensures the API absolutely waits for the complete JSON response
with the matching request ID before serving any reply to clients.
parent c0d398f4
...@@ -603,18 +603,19 @@ async def detect_json_response_with_id(page, container_selector, request_id, pro ...@@ -603,18 +603,19 @@ async def detect_json_response_with_id(page, container_selector, request_id, pro
}; };
const observer = new MutationObserver((mutations) => { const observer = new MutationObserver((mutations) => {
// Only resolve if we have complete, valid JSON // Only resolve if we have complete, valid JSON with exact ID match
const result = getCompleteJsonResponse(); const result = getCompleteJsonResponse();
if (result && !result.startsWith("Error:")) { if (result && typeof result === 'string' && result.length > 0) {
console.log(`🎯 Observer found complete response, disconnecting...`);
observer.disconnect(); observer.disconnect();
resolveOnce(result); resolveOnce(result);
return; return;
} }
// Update best partial match for debugging // Log progress for debugging but don't resolve yet
if (partialJsonContent.length > (bestMatch?.length || 0)) { const hasPartialId = container.textContent && container.textContent.includes(requestId);
bestMatch = partialJsonContent; if (hasPartialId) {
console.log(`Updated partial match: ${partialJsonContent.substring(0, 100)}...`); console.log(`⏳ Found request ID in content, waiting for complete JSON...`);
} }
}); });
...@@ -624,45 +625,77 @@ async def detect_json_response_with_id(page, container_selector, request_id, pro ...@@ -624,45 +625,77 @@ async def detect_json_response_with_id(page, container_selector, request_id, pro
characterData: true characterData: true
}); });
// Function to validate complete JSON with both required keys // Function to validate complete JSON with both required keys and exact ID match
const isCompleteValidJson = (text) => { const isCompleteValidJson = (text) => {
try { try {
const jsonObj = JSON.parse(text); const jsonObj = JSON.parse(text);
return jsonObj.id && jsonObj.id.includes(requestId) && // Strict validation: must have exact ID match and non-empty response
jsonObj.response && typeof jsonObj.response === 'string' && const hasValidId = jsonObj.id &&
jsonObj.response.length > 0; typeof jsonObj.id === 'string' &&
jsonObj.id.includes(requestId) &&
jsonObj.id.length >= requestId.length;
const hasValidResponse = jsonObj.response &&
typeof jsonObj.response === 'string' &&
jsonObj.response.trim().length > 0;
if (hasValidId && hasValidResponse) {
console.log(`✓ Complete valid JSON found - ID: ${jsonObj.id}, Response length: ${jsonObj.response.length}`);
return true;
} else {
console.log(`✗ Incomplete JSON - ID valid: ${hasValidId}, Response valid: ${hasValidResponse}`);
return false;
}
} catch (e) { } catch (e) {
console.log(`✗ JSON parse error: ${e.message}`);
return false; return false;
} }
}; };
// Enhanced check that only returns complete, valid JSON // Enhanced check that only returns complete, valid JSON with exact ID match
const getCompleteJsonResponse = () => { const getCompleteJsonResponse = () => {
const htmlResult = extractJsonFromHtml(); console.log(`🔍 Searching for complete JSON with ID: ${requestId}`);
if (htmlResult) {
// Verify we have a complete JSON by trying to find the original JSON // First priority: Check HTML formatted code blocks
const codeBlocks = container.querySelectorAll([ const codeBlocks = container.querySelectorAll([
'pre code.language-json', 'pre code.language-json',
'pre code[class*="json"]', 'pre code[class*="json"]',
'code.language-json', 'code.language-json',
'code[class*="json"]', 'code[class*="json"]',
'pre code', 'pre code',
'code' 'code'
].join(', ')); ].join(', '));
for (const codeBlock of codeBlocks) { for (const codeBlock of codeBlocks) {
const jsonText = codeBlock.textContent ? codeBlock.textContent.trim() : ''; const jsonText = codeBlock.textContent ? codeBlock.textContent.trim() : '';
if (jsonText && isCompleteValidJson(jsonText)) { if (jsonText && jsonText.includes(requestId)) {
console.log(`Found complete valid JSON: ${jsonText.substring(0, 100)}...`); console.log(`📋 Found code block with request ID: ${jsonText.substring(0, 150)}...`);
if (isCompleteValidJson(jsonText)) {
const jsonObj = JSON.parse(jsonText); const jsonObj = JSON.parse(jsonText);
console.log(`✅ Returning validated response for ID: ${jsonObj.id}`);
return jsonObj.response; return jsonObj.response;
} }
} }
} }
// Fallback to text-based extraction with validation // Second priority: Check all text content for JSON patterns
const result = getCombinedText(); const allElements = container.querySelectorAll('*');
return result; for (const element of allElements) {
const text = element.textContent ? element.textContent.trim() : '';
if (text && text.includes(requestId) && text.includes('{') && text.includes('"response"')) {
console.log(`📄 Found element with potential JSON: ${text.substring(0, 150)}...`);
// Try to extract JSON from this text
const jsonMatch = text.match(/\{[^{}]*"id"[^{}]*"' + requestId + '"[^{}]*"response"[^{}]*\}|\{[^{}]*"response"[^{}]*"id"[^{}]*"' + requestId + '"[^{}]*\}/);
if (jsonMatch && isCompleteValidJson(jsonMatch[0])) {
const jsonObj = JSON.parse(jsonMatch[0]);
console.log(`✅ Returning validated response from text for ID: ${jsonObj.id}`);
return jsonObj.response;
}
}
}
console.log(`❌ No complete JSON found with ID: ${requestId}`);
return null;
}; };
// Initial check after a longer delay to allow content to load // Initial check after a longer delay to allow content to load
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment