2025-12-26 12:45:23 -08:00
|
|
|
|
<!DOCTYPE html>
|
|
|
|
|
|
<html>
|
|
|
|
|
|
<head>
|
|
|
|
|
|
<title>Server Diagnostic - Multi-User Transcription</title>
|
|
|
|
|
|
<meta charset="UTF-8">
|
|
|
|
|
|
<style>
|
|
|
|
|
|
body {
|
|
|
|
|
|
font-family: Arial, sans-serif;
|
|
|
|
|
|
max-width: 900px;
|
|
|
|
|
|
margin: 40px auto;
|
|
|
|
|
|
padding: 20px;
|
|
|
|
|
|
background: #f5f5f5;
|
|
|
|
|
|
}
|
|
|
|
|
|
.test {
|
|
|
|
|
|
background: white;
|
|
|
|
|
|
padding: 20px;
|
|
|
|
|
|
margin: 15px 0;
|
|
|
|
|
|
border-radius: 5px;
|
|
|
|
|
|
border-left: 4px solid #ccc;
|
|
|
|
|
|
}
|
|
|
|
|
|
.test.pass { border-color: #4CAF50; }
|
|
|
|
|
|
.test.fail { border-color: #f44336; }
|
|
|
|
|
|
.test.warn { border-color: #ff9800; }
|
|
|
|
|
|
.test h3 {
|
|
|
|
|
|
margin-top: 0;
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
}
|
|
|
|
|
|
.test pre {
|
|
|
|
|
|
background: #f5f5f5;
|
|
|
|
|
|
padding: 10px;
|
|
|
|
|
|
border-radius: 3px;
|
|
|
|
|
|
overflow-x: auto;
|
|
|
|
|
|
}
|
|
|
|
|
|
.status { font-weight: bold; }
|
|
|
|
|
|
.pass .status { color: #4CAF50; }
|
|
|
|
|
|
.fail .status { color: #f44336; }
|
|
|
|
|
|
.warn .status { color: #ff9800; }
|
|
|
|
|
|
h1 { color: #333; }
|
|
|
|
|
|
.info { background: #e3f2fd; padding: 15px; border-radius: 5px; margin: 20px 0; }
|
|
|
|
|
|
</style>
|
|
|
|
|
|
</head>
|
|
|
|
|
|
<body>
|
|
|
|
|
|
<h1>🔧 Server Diagnostic</h1>
|
|
|
|
|
|
|
|
|
|
|
|
<?php
|
|
|
|
|
|
require_once 'config.php';
|
|
|
|
|
|
|
|
|
|
|
|
// Test 1: PHP Version
|
|
|
|
|
|
$php_version = phpversion();
|
|
|
|
|
|
$php_ok = version_compare($php_version, '7.4.0', '>=');
|
|
|
|
|
|
?>
|
|
|
|
|
|
<div class="test <?php echo $php_ok ? 'pass' : 'fail'; ?>">
|
|
|
|
|
|
<h3>PHP Version</h3>
|
|
|
|
|
|
<p class="status"><?php echo $php_ok ? '✓ PASS' : '✗ FAIL'; ?></p>
|
|
|
|
|
|
<p>Version: <strong><?php echo $php_version; ?></strong></p>
|
|
|
|
|
|
<?php if (!$php_ok): ?>
|
|
|
|
|
|
<p>Minimum required: PHP 7.4.0</p>
|
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<?php
|
|
|
|
|
|
// Test 2: Server API
|
|
|
|
|
|
$server_api = php_sapi_name();
|
|
|
|
|
|
$is_fpm = strpos($server_api, 'fpm') !== false;
|
|
|
|
|
|
?>
|
|
|
|
|
|
<div class="test pass">
|
|
|
|
|
|
<h3>Server API</h3>
|
|
|
|
|
|
<p class="status">ℹ INFO</p>
|
|
|
|
|
|
<p>SAPI: <strong><?php echo $server_api; ?></strong></p>
|
|
|
|
|
|
<p>Type: <strong><?php echo $is_fpm ? 'PHP-FPM' : 'Other'; ?></strong></p>
|
|
|
|
|
|
<?php if ($is_fpm): ?>
|
|
|
|
|
|
<p class="info">✓ Running under PHP-FPM. Note: php_flag/php_value directives in .htaccess won't work. Configure PHP settings in php.ini or FPM pool config.</p>
|
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<?php
|
|
|
|
|
|
// Test 3: Storage Directory
|
|
|
|
|
|
$storage_exists = file_exists(STORAGE_DIR);
|
|
|
|
|
|
$storage_writable = $storage_exists && is_writable(STORAGE_DIR);
|
|
|
|
|
|
$storage_ok = $storage_exists && $storage_writable;
|
|
|
|
|
|
?>
|
|
|
|
|
|
<div class="test <?php echo $storage_ok ? 'pass' : 'fail'; ?>">
|
|
|
|
|
|
<h3>Storage Directory</h3>
|
|
|
|
|
|
<p class="status"><?php echo $storage_ok ? '✓ PASS' : '✗ FAIL'; ?></p>
|
|
|
|
|
|
<p>Path: <code><?php echo STORAGE_DIR; ?></code></p>
|
|
|
|
|
|
<p>Exists: <?php echo $storage_exists ? 'Yes' : 'No'; ?></p>
|
|
|
|
|
|
<p>Writable: <?php echo $storage_writable ? 'Yes' : 'No'; ?></p>
|
|
|
|
|
|
<?php if (!$storage_ok): ?>
|
|
|
|
|
|
<p><strong>Fix:</strong> Run: <code>mkdir -p <?php echo STORAGE_DIR; ?> && chmod 755 <?php echo STORAGE_DIR; ?></code></p>
|
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<?php
|
|
|
|
|
|
// Test 4: Required PHP Extensions
|
|
|
|
|
|
$required_extensions = ['json', 'mbstring'];
|
|
|
|
|
|
$missing_extensions = [];
|
|
|
|
|
|
foreach ($required_extensions as $ext) {
|
|
|
|
|
|
if (!extension_loaded($ext)) {
|
|
|
|
|
|
$missing_extensions[] = $ext;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
$extensions_ok = empty($missing_extensions);
|
|
|
|
|
|
?>
|
|
|
|
|
|
<div class="test <?php echo $extensions_ok ? 'pass' : 'fail'; ?>">
|
|
|
|
|
|
<h3>PHP Extensions</h3>
|
|
|
|
|
|
<p class="status"><?php echo $extensions_ok ? '✓ PASS' : '✗ FAIL'; ?></p>
|
|
|
|
|
|
<?php if ($extensions_ok): ?>
|
|
|
|
|
|
<p>All required extensions loaded</p>
|
|
|
|
|
|
<?php else: ?>
|
|
|
|
|
|
<p>Missing extensions: <strong><?php echo implode(', ', $missing_extensions); ?></strong></p>
|
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<?php
|
|
|
|
|
|
// Test 5: Server Info
|
|
|
|
|
|
?>
|
|
|
|
|
|
<div class="test pass">
|
|
|
|
|
|
<h3>Server Information</h3>
|
|
|
|
|
|
<p class="status">ℹ INFO</p>
|
|
|
|
|
|
<p>Server: <strong><?php echo $_SERVER['SERVER_SOFTWARE'] ?? 'Unknown'; ?></strong></p>
|
|
|
|
|
|
<p>Document Root: <code><?php echo $_SERVER['DOCUMENT_ROOT'] ?? 'Unknown'; ?></code></p>
|
|
|
|
|
|
<p>Script Path: <code><?php echo __DIR__; ?></code></p>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<?php
|
|
|
|
|
|
// Test 6: API Endpoint Test
|
|
|
|
|
|
?>
|
|
|
|
|
|
<div class="test pass">
|
|
|
|
|
|
<h3>API Endpoint Test</h3>
|
|
|
|
|
|
<p class="status">ℹ INFO</p>
|
|
|
|
|
|
<p>Info endpoint: <a href="server.php?action=info" target="_blank">server.php?action=info</a></p>
|
|
|
|
|
|
<p>Test this endpoint to verify the API is accessible</p>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<?php
|
|
|
|
|
|
// Test 7: Server-Sent Events Test
|
|
|
|
|
|
?>
|
|
|
|
|
|
<div class="test pass">
|
|
|
|
|
|
<h3>Server-Sent Events (SSE) Test</h3>
|
|
|
|
|
|
<p class="status">Testing...</p>
|
|
|
|
|
|
<div id="sse-status">Connecting to SSE endpoint...</div>
|
|
|
|
|
|
<div id="sse-log" style="background: #f5f5f5; padding: 10px; margin-top: 10px; border-radius: 3px; max-height: 200px; overflow-y: auto;"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="info">
|
|
|
|
|
|
<h3>Common Issues & Solutions</h3>
|
|
|
|
|
|
<ul>
|
|
|
|
|
|
<li><strong>Disconnected Status:</strong> Check that server.php is accessible and SSE test above succeeds</li>
|
|
|
|
|
|
<li><strong>403 Forbidden:</strong> Check file permissions (644 for files, 755 for directories)</li>
|
|
|
|
|
|
<li><strong>500 Internal Server Error:</strong> Check PHP error logs for details</li>
|
|
|
|
|
|
<li><strong>CORS Errors:</strong> Ensure ENABLE_CORS is true in config.php</li>
|
|
|
|
|
|
<li><strong>PHP-FPM Issues:</strong> Check that PHP-FPM is running and configured correctly</li>
|
|
|
|
|
|
</ul>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
|
// Test SSE connection
|
|
|
|
|
|
const sseLog = document.getElementById('sse-log');
|
|
|
|
|
|
const sseStatus = document.getElementById('sse-status');
|
|
|
|
|
|
|
|
|
|
|
|
function log(message) {
|
|
|
|
|
|
const time = new Date().toLocaleTimeString();
|
|
|
|
|
|
sseLog.innerHTML += `[${time}] ${message}<br>`;
|
|
|
|
|
|
sseLog.scrollTop = sseLog.scrollHeight;
|
2025-12-26 13:57:28 -08:00
|
|
|
|
console.log(`[SSE Test] ${message}`);
|
2025-12-26 12:45:23 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Create test room
|
|
|
|
|
|
const testRoom = 'diagnostic-test-' + Date.now();
|
|
|
|
|
|
const url = `server.php?action=stream&room=${encodeURIComponent(testRoom)}`;
|
|
|
|
|
|
|
2025-12-26 13:57:28 -08:00
|
|
|
|
console.group('SSE Connection Test');
|
|
|
|
|
|
console.log('Test Room:', testRoom);
|
|
|
|
|
|
console.log('Full URL:', url);
|
|
|
|
|
|
console.log('Current Location:', window.location.href);
|
|
|
|
|
|
console.log('Base URL:', window.location.origin + window.location.pathname.replace(/\/[^\/]*$/, '/'));
|
|
|
|
|
|
|
2025-12-26 12:45:23 -08:00
|
|
|
|
log(`Attempting to connect to: ${url}`);
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
const eventSource = new EventSource(url);
|
|
|
|
|
|
|
2025-12-26 13:57:28 -08:00
|
|
|
|
console.log('EventSource object created:', eventSource);
|
|
|
|
|
|
console.log('EventSource readyState:', eventSource.readyState, '(0=CONNECTING, 1=OPEN, 2=CLOSED)');
|
|
|
|
|
|
console.log('EventSource url:', eventSource.url);
|
|
|
|
|
|
|
|
|
|
|
|
eventSource.onopen = (event) => {
|
|
|
|
|
|
console.log('EventSource.onopen fired:', event);
|
|
|
|
|
|
console.log('ReadyState after open:', eventSource.readyState);
|
2025-12-26 12:45:23 -08:00
|
|
|
|
sseStatus.innerHTML = '<span style="color: #4CAF50; font-weight: bold;">✓ SSE Connected</span>';
|
|
|
|
|
|
log('✓ Connection established');
|
|
|
|
|
|
log('✓ Server-Sent Events are working');
|
|
|
|
|
|
|
|
|
|
|
|
// Close after successful connection
|
|
|
|
|
|
setTimeout(() => {
|
2025-12-26 13:57:28 -08:00
|
|
|
|
console.log('Closing EventSource after successful test');
|
2025-12-26 12:45:23 -08:00
|
|
|
|
eventSource.close();
|
|
|
|
|
|
log('Connection test complete - closing');
|
2025-12-26 13:57:28 -08:00
|
|
|
|
console.groupEnd();
|
2025-12-26 12:45:23 -08:00
|
|
|
|
}, 2000);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
eventSource.onmessage = (event) => {
|
2025-12-26 13:57:28 -08:00
|
|
|
|
console.log('EventSource.onmessage:', event);
|
|
|
|
|
|
console.log('Message data:', event.data);
|
|
|
|
|
|
console.log('Event ID:', event.lastEventId);
|
2025-12-26 12:45:23 -08:00
|
|
|
|
log('Received message: ' + event.data);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
eventSource.onerror = (error) => {
|
2025-12-26 13:57:28 -08:00
|
|
|
|
console.error('EventSource.onerror fired:', error);
|
|
|
|
|
|
console.error('ReadyState on error:', eventSource.readyState);
|
|
|
|
|
|
console.error('EventSource URL:', eventSource.url);
|
|
|
|
|
|
|
|
|
|
|
|
// Try to get more info from the error
|
|
|
|
|
|
console.error('Error type:', error.type);
|
|
|
|
|
|
console.error('Error target:', error.target);
|
|
|
|
|
|
console.error('Error currentTarget:', error.currentTarget);
|
|
|
|
|
|
|
|
|
|
|
|
// Check if it's a network error
|
|
|
|
|
|
if (eventSource.readyState === EventSource.CLOSED) {
|
|
|
|
|
|
console.error('Connection is CLOSED - this usually indicates a network error or server rejection');
|
|
|
|
|
|
} else if (eventSource.readyState === EventSource.CONNECTING) {
|
|
|
|
|
|
console.warn('Still CONNECTING - may be retrying');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-26 12:45:23 -08:00
|
|
|
|
sseStatus.innerHTML = '<span style="color: #f44336; font-weight: bold;">✗ SSE Failed</span>';
|
|
|
|
|
|
log('✗ Connection error occurred');
|
2025-12-26 13:57:28 -08:00
|
|
|
|
log('ReadyState: ' + eventSource.readyState + ' (0=CONNECTING, 1=OPEN, 2=CLOSED)');
|
|
|
|
|
|
log('Check browser console for detailed error information');
|
|
|
|
|
|
|
2025-12-26 12:45:23 -08:00
|
|
|
|
eventSource.close();
|
2025-12-26 13:57:28 -08:00
|
|
|
|
console.groupEnd();
|
2025-12-26 12:45:23 -08:00
|
|
|
|
};
|
2025-12-26 13:57:28 -08:00
|
|
|
|
|
|
|
|
|
|
// Monitor readyState changes
|
|
|
|
|
|
let lastReadyState = eventSource.readyState;
|
|
|
|
|
|
const stateMonitor = setInterval(() => {
|
|
|
|
|
|
if (eventSource.readyState !== lastReadyState) {
|
|
|
|
|
|
console.log('ReadyState changed:', lastReadyState, '→', eventSource.readyState);
|
|
|
|
|
|
lastReadyState = eventSource.readyState;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (eventSource.readyState === EventSource.CLOSED) {
|
|
|
|
|
|
clearInterval(stateMonitor);
|
|
|
|
|
|
}
|
|
|
|
|
|
}, 100);
|
|
|
|
|
|
|
2025-12-26 12:45:23 -08:00
|
|
|
|
} catch (error) {
|
2025-12-26 13:57:28 -08:00
|
|
|
|
console.error('Exception creating EventSource:', error);
|
|
|
|
|
|
console.error('Error stack:', error.stack);
|
2025-12-26 12:45:23 -08:00
|
|
|
|
sseStatus.innerHTML = '<span style="color: #f44336; font-weight: bold;">✗ SSE Error</span>';
|
|
|
|
|
|
log('✗ Exception: ' + error.message);
|
2025-12-26 13:57:28 -08:00
|
|
|
|
console.groupEnd();
|
2025-12-26 12:45:23 -08:00
|
|
|
|
}
|
|
|
|
|
|
</script>
|
|
|
|
|
|
</body>
|
|
|
|
|
|
</html>
|